Esempio n. 1
0
static void*
stream_blocking_thread(void* arg) {
	int iloop;

	socket_t* sock = (socket_t*)arg;

	char buffer_out[317] = {0};
	char buffer_in[317] = {0};

	stream_t* stream = socket_stream(sock);

	for (iloop = 0; !thread_try_wait(0) && iloop < 512; ++iloop) {
		log_infof(HASH_NETWORK, STRING_CONST("UDP write pass %d"), iloop);
		EXPECT_SIZEEQ(stream_write(stream, buffer_out, 127), 127);
		EXPECT_SIZEEQ(stream_write(stream, buffer_out + 127, 180), 180);
		stream_flush(stream);
		EXPECT_SIZEEQ(stream_write(stream, buffer_out + 307, 10), 10);
		stream_flush(stream);
		log_infof(HASH_NETWORK, STRING_CONST("UDP read pass %d"), iloop);
		EXPECT_SIZEEQ(stream_read(stream, buffer_in, 235), 235);
		EXPECT_SIZEEQ(stream_read(stream, buffer_in + 235, 82), 82);
		thread_yield();
	}

	log_debugf(HASH_NETWORK, STRING_CONST("IO complete on socket 0x%llx"), sock);
	stream_deallocate(stream);

	return 0;
}
Esempio n. 2
0
static void server_flush(server_t server) {
	stream_t s;
	debug("flushing the streams\n");
	for (s = server->used_chain; s != NULL; s = s->next) { 
		stream_flush(s);
	}
}
Esempio n. 3
0
static bool stream_message_start(stream_t stream, unsigned int chan) {
	ShubMessageHdr *msg;

	if (!stream->good) {
		return false;
	}

	if (stream->output.curmessage) {
		shout("cannot start new message while the old one is unfinished\n");
		stream->good = false;
		return false;
	}

	if (BUFFER_SIZE - stream->output.ready < sizeof(ShubMessageHdr)) {
		if (!stream_flush(stream)) {
			shout("failed to flush before starting new message\n");
			stream->good = false;
			return false;
		}
	}

	msg = stream->output.curmessage = (ShubMessageHdr*)(stream->output.data + stream->output.ready);
	msg->size = 0;
	msg->code = 'r';
	msg->chan = chan;

	return true;
}
Esempio n. 4
0
/**
 * Return information 
 */
static void _dump_events(gds_stream_t * stream, sched_t * self)
{
  sched_static_t * sched= (sched_static_t *) self;
  _event_t * event;
  uint32_t depth;
  uint32_t max_depth;
  uint32_t start;
  unsigned int index;

  depth= sched->events->current_depth;
  max_depth= sched->events->max_depth;
  start= sched->events->start_index;
  stream_printf(stream, "Number of events queued: %u (%u)\n",
	     depth, max_depth);
  for (index= 0; index < depth; index++) {
    event= (_event_t *) sched->events->items[(start+index) % max_depth];
    stream_printf(stream, "(%d) ", (start+index) % max_depth);
    stream_flush(stream);
    if (event->ops->dump != NULL) {
      event->ops->dump(stream, event->ctx);
    } else {
      stream_printf(stream, "unknown");
    }
    stream_printf(stream, "\n");
  }
}
Esempio n. 5
0
/**
 * cdk_stream_get_length: Return the length of the associated file handle.
 * @s: The STREAM object.
 *
 * This function should work for both read and write streams. For write
 * streams an additional flush is used to write possible pending data.
 **/
off_t
cdk_stream_get_length (cdk_stream_t s)
{
    struct stat statbuf;
    cdk_error_t rc;

    if (!s)
    {
        gnutls_assert ();
        return (off_t) - 1;
    }

    /* The user callback does not support stat. */
    if (s->cbs_hd)
        return 0;

    rc = stream_flush (s);
    if (rc)
    {
        s->error = rc;
        gnutls_assert ();
        return (off_t) - 1;
    }

    if (fstat (fileno (s->fp), &statbuf))
    {
        s->error = CDK_File_Error;
        gnutls_assert ();
        return (off_t) - 1;
    }

    return statbuf.st_size;
}
Esempio n. 6
0
void xmpp_close(void)
{
    if (session.wfs < 0)
        return;

    /* Close stream */
    {
        char *s;
        FORMAT(s,
               "<iq to='%s' type='get'>"
               "<query xmlns='urn:cryonline:k01'>"
               "<player_status prev_status='%u' new_status='%u' to='%s'/>"
               "</query>"
               "</iq>",
               session.online.jid.k01,
               session.online.status,
               STATUS_LEFT,
               session.online.channel ? session.online.channel : "");
        stream_send_msg(session.wfs, s);
        free(s);
    }

    stream_send_msg(session.wfs, "</stream:stream>");
    stream_flush(session.wfs);
    close(session.wfs);

    session.wfs = -1;

#ifdef USE_TLS
    tls_close();
    tls_free();
#endif
}
Esempio n. 7
0
void *thread_sendstream(void *vargs)
{
    struct thread *t = (struct thread *) vargs;

    thread_register_sigint_handler();

    do {
        char *msg = thread_sendstream_get_next_msg();

        stream_send_msg(session.wfs, msg);
        stream_flush(session.wfs);

        free(msg);
    } while (session.active);

    /* Destroy remaining messages */
    for (unsigned int i = 0; i < SEND_MSG_MAX; ++i)
    {
        free(send_msgs[i]);
        send_msgs[i] = NULL;
    }

    sem_destroy(&_sem_send_msgs_empty);
    sem_destroy(&_sem_send_msgs_full);

    return thread_close(t);
}
Esempio n. 8
0
/**
 * cdk_stream_write: Try to write count bytes into the stream.
 * @s: The STREAM object
 * @buf: The buffer with the values to write.
 * @count: The size of the buffer.
 *
 * In this function we simply write the bytes to the stream. We can't
 * use the filters here because it would mean they have to support
 * partial flushing.
 **/
int
cdk_stream_write( cdk_stream_t s, const void * buf, size_t count )
{
    int nwritten;

    if( !s )
        return CDK_Inv_Value;
    
    if( !s->flags.write )
        return CDK_Inv_Mode; /* this is a read stream */

    if( !buf && !count )
        return stream_flush( s );

    if( s->cache.on ) {
        if( s->cache.size + count > sizeof( s->cache.buf ) )
            return CDK_EOF;
        memcpy( s->cache.buf + s->cache.size, buf, count  );
        s->cache.size += count;
        return 0;
    }
  
    nwritten = fwrite( buf, 1, count, s->fp );
    if( !nwritten )
        nwritten = EOF;  
    return nwritten;
}
Esempio n. 9
0
int vrt_rdev_create_superblocks(vrt_realdev_t *rdev)
{
    superblock_header_t header;
    int i, err;

    for (i = 0; i < 2; i++)
    {
        uint64_t start, end;

        __get_superblock_data_range(i, &start, &end);

        header.magic = SUPERBLOCK_HEADER_MAGIC;
        header.format = SUPERBLOCK_HEADER_FORMAT;
        header.position = i;
        header.reserved1 = 0;
        header.sb_version = 0;
        header.data_max_size = end - start + 1;
        header.data_offset = start;
        header.data_size = 0;
        header.checksum = 0;
        memset(header.reserved2, 0, sizeof(header.reserved2));

        err = __write_sb_header(rdev, &header);
        if (err != 0)
            return err;
    }

    return stream_flush(rdev->raw_sb_stream);
}
Esempio n. 10
0
int downloadData()
{
  char device[255];
  sprintf(device, "/dev/tcp/%s/80", "netdata.be");
  char headers[255];
  sprintf(headers, "GET /loxone/test2.php HTTP/1.1\r\nHost: %s\r\nUser-Agent: LoxLIVE [en]\r\nContent-Type: text/html; charset=utf-8\r\n\r\n",  "netdata.be");
  STREAM* tcpStream = stream_create(device, 0, 0);
  stream_write(tcpStream, headers, strlen(headers));
  stream_flush(tcpStream);

  char block[RD_BLOCK_SIZE];
  int count;
  int i = 0;
  // read stream
  do
  {
    count = stream_read(tcpStream, block, RD_BLOCK_SIZE, 4000);
    if (count > 0) strncpy((char*)buffer + i * RD_BLOCK_SIZE, block, count);
    i++;
    if (i >= ( ( MAX_BUFF - 1 ) / RD_BLOCK_SIZE )) count=0; // avoid buffer overflows

  }
  while (count > 0);
  stream_close(tcpStream);
  buffer[MAX_BUFF] = 0; //put null character or end of string at the end.
  return 0;
}
Esempio n. 11
0
static bool stream_message_append(stream_t stream, size_t len, void *data) {
	ShubMessageHdr *msg;

	debug("appending %d\n", *(int*)data);

	if (stream->output.curmessage == NULL) {
		shout("cannot append, the message was not started\n");
		stream->good = false;
		return false;
	}

	int newsize = stream->output.curmessage->size + sizeof(ShubMessageHdr) + len;
	if (newsize > BUFFER_SIZE) {
		// the flushing will not help here
		shout("the message cannot be bigger than the buffer size\n");
		stream->good = false;
		return false;
	}

	if (stream->output.ready + newsize > BUFFER_SIZE) {
		if (!stream_flush(stream)) {
			shout("failed to flush before extending the message\n");
			stream->good = false;
			return false;
		}
	}

	msg = stream->output.curmessage;
	memcpy((char*)msg + msg->size + sizeof(ShubMessageHdr), data, len);
	msg->size += len;

	return true;
}
Esempio n. 12
0
static void server_flush(server_t server) {
	debug("flushing the streams\n");
	int i;
	for (i = 0; i < server->streamsnum; i++) {
		stream_t stream = server->streams + i;
		stream_flush(stream);
	}
}
Esempio n. 13
0
/* TODO stream is very inefficient of transmiting when receive -
 *      receiver forces transmiter to accasionaly flush out-buffer
 * */
static unsigned short
tcp_stream_getchar (tcp_stream_t *u)
{
	unsigned short c;
	tcp_socket_t*  s = u->socket;

	if (!s)
		return -1;
	mutex_lock (&s->lock);

	/* Flush output buffer. */
	if (u->outptr > u->outdata) {
		stream_flush (u);
		mutex_unlock (&s->lock);
		socket_flush (s);
		mutex_lock (&s->lock);
	}

	if (u->inbuf)
		mutex_unlock (&s->lock);
	else {
	    /* Wait for data. */
		while (tcp_queue_is_empty (s)) {
			if (!tcp_socket_is_state(s, TCP_STATES_TRANSFER)) {
				mutex_unlock (&s->lock);
				return -1;
			}
			mutex_wait (&s->lock);
		}
		u->inbuf = tcp_queue_get (s);
		u->inptr = u->inbuf->payload;
		mutex_unlock (&s->lock);
/*debug_printf ("tstream input"); buf_print (u->inbuf);*/

		mutex_lock (&s->ip->lock);
		if (! (s->flags & TF_ACK_DELAY) &&
		    ! (s->flags & TF_ACK_NOW)) {
			tcp_ack (s);
		}
		mutex_unlock (&s->ip->lock);
	}

	/* Get byte from buffer. */
	c = *u->inptr++;
	if (u->inptr >= u->inbuf->payload + u->inbuf->len) {
		buf_t *old = u->inbuf;

		u->inbuf = old->next;
		if (u->inbuf) {
			u->inptr = u->inbuf->payload;
			old->next = 0;
		}
		buf_free (old);
	}
	return c;
}
Esempio n. 14
0
/**
 * cdk_stream_write: 
 * @s: The STREAM object
 * @buf: The buffer with the values to write.
 * @count: The size of the buffer.
 *
 * Tries to write count bytes into the stream.
 * In this function we simply write the bytes to the stream. We can't
 * use the filters here because it would mean they have to support
 * partial flushing.
 **/
int
cdk_stream_write (cdk_stream_t s, const void *buf, size_t count)
{
  int nwritten;

  if (!s)
    {
      s->error = CDK_Inv_Value;
      gnutls_assert();
      return EOF;
    }

  if (s->cbs_hd)
    {
      if (s->cbs.write)
	return s->cbs.write (s->cbs_hd, buf, count);
      return 0;
    }

  if (!s->flags.write)
    {
      s->error = CDK_Inv_Mode;	/* this is a read stream */
      gnutls_assert();
      return EOF;
    }

  if (!buf && !count)
    return stream_flush (s);

  if (s->cache.on)
    {
      /* We need to resize the buffer if the additional data wouldn't
         fit into it. We allocate more memory to avoid to resize it the
         next time the function is used. */
      if (s->cache.size + count > s->cache.alloced)
	{
	  byte *old = s->cache.buf;

	  s->cache.buf =
	    cdk_calloc (1, s->cache.alloced + count + STREAM_BUFSIZE);
	  s->cache.alloced += (count + STREAM_BUFSIZE);
	  memcpy (s->cache.buf, old, s->cache.size);
	  cdk_free (old);
	  _cdk_log_debug ("stream: enlarge cache to %d octets\n",
			  s->cache.alloced);
	}
      memcpy (s->cache.buf + s->cache.size, buf, count);
      s->cache.size += count;
      return count;
    }

  nwritten = fwrite (buf, 1, count, s->fp);
  if (!nwritten)
    nwritten = EOF;
  return nwritten;
}
Esempio n. 15
0
int stream_write (struct stream *stream, const char *buf, size_t size)
{
    int err;

    // our write buffer must be empty, since _stream_write_direct will bypass it
    if ((err = stream_flush(stream)))
        return err;

    return _stream_write_direct(stream, buf, size);
}
Esempio n. 16
0
static inline void ___ipip_debug(const char * msg, ...)
{
#ifdef IPIP_DEBUG
  va_list ap;

  va_start(ap, msg);
  stream_printf(gdsout, "IPIP_DBG::");
  str_format_for_each(gdsout, _debug_for_each, &ap, msg);
  stream_flush(gdsout);
  va_end(ap);
#endif /* IPIP_DEBUG */
}
Esempio n. 17
0
int vrt_rdev_end_superblock_write(vrt_realdev_t *rdev, superblock_write_op_t *op)
{
    int err;

    op->header.sb_version = op->new_sb_version;
    op->header.data_size = checksum_stream_get_size(op->stream);
    op->header.checksum = checksum_stream_get_value(op->stream);

    err =  __write_sb_header(rdev, &op->header);
    if (err != 0)
        return err;

    return stream_flush(rdev->raw_sb_stream);
}
Esempio n. 18
0
void cdc_acmd_class_suspend(USBD* usbd, void* param)
{
    CDC_ACMD* cdc_acmd = (CDC_ACMD*)param;
#if (USBD_CDC_ACM_TX_STREAM_SIZE)
    stream_stop_listen(cdc_acmd->tx_stream);
    stream_flush(cdc_acmd->tx_stream);
    usbd_usb_ep_flush(usbd, USB_EP_IN | cdc_acmd->data_ep);
    cdc_acmd->tx_idle = true;
    cdc_acmd->tx_size = 0;
#endif //USBD_CDC_ACM_TX_STREAM_SIZE
#if (USBD_CDC_ACM_RX_STREAM_SIZE)
    stream_flush(cdc_acmd->rx_stream);
    usbd_usb_ep_flush(usbd, cdc_acmd->data_ep);
    cdc_acmd->rx_free = 0;
#endif //USBD_CDC_ACM_RX_STREAM_SIZE

    if (cdc_acmd->control_ep)
    {
        usbd_usb_ep_flush(usbd, USB_EP_IN | cdc_acmd->control_ep);
        cdc_acmd->notify_busy = cdc_acmd->notify_pending = false;
    }
    cdc_acmd->suspended = true;
}
Esempio n. 19
0
void cdc_acmd_class_reset(USBD* usbd, void* param)
{
    CDC_ACMD* cdc_acmd = (CDC_ACMD*)param;

#if (USBD_CDC_ACM_TX_STREAM_SIZE)
    stream_stop_listen(cdc_acmd->tx_stream);
    stream_flush(cdc_acmd->tx_stream);
    usbd_usb_ep_close(usbd, USB_EP_IN | cdc_acmd->data_ep);
#endif //USBD_CDC_ACM_TX_STREAM_SIZE
#if (USBD_CDC_ACM_RX_STREAM_SIZE)
    stream_flush(cdc_acmd->rx_stream);
    usbd_usb_ep_close(usbd, cdc_acmd->data_ep);
#endif //USBD_CDC_ACM_RX_STREAM_SIZE

    usbd_unregister_endpoint(usbd, cdc_acmd->data_iface, cdc_acmd->data_ep);
    usbd_unregister_interface(usbd, cdc_acmd->data_iface, &__CDC_ACMD_CLASS);
    if (cdc_acmd->control_ep)
    {
        usbd_usb_ep_close(usbd, USB_EP_IN | cdc_acmd->control_ep);
        usbd_unregister_endpoint(usbd, cdc_acmd->control_iface, cdc_acmd->control_ep);
        usbd_unregister_interface(usbd, cdc_acmd->control_iface, &__CDC_ACMD_CLASS);
    }
    cdc_acmd_destroy(cdc_acmd);
}
Esempio n. 20
0
/* Model output function */
void client_output(int_T tid)
{
  /* local block i/o variables */
  t_stream_ptr rtb_StreamFlush_o1;

  /* S-Function (stream_connect_block): '<Root>/Stream Connect' */
  /* S-Function Block: client/Stream Connect (stream_connect_block) */
  {
    t_error result;
    result = stream_connect("tcpip://localhost:18000", true,
      client_P.StreamConnect_SendBufferSize,
      client_P.StreamConnect_ReceiveBufferSize,
      &client_DWork.StreamConnect_Stream);
    if (result == 0) {
      static const t_short endian_test = 0x0201;
      result = stream_set_swap_bytes(client_DWork.StreamConnect_Stream, *(t_byte
        *)&endian_test != client_P.StreamConnect_Endian);
    }
  }

  /* Sin: '<Root>/Sine Wave' */
  client_B.SineWave = sin(client_P.SineWave_Freq * client_M->Timing.t[0] +
    client_P.SineWave_Phase) * client_P.SineWave_Amp + client_P.SineWave_Bias;

  /* S-Function (stream_send_block): '<Root>/Stream Send' incorporates:
   *  S-Function (stream_connect_block): '<Root>/Stream Connect'
   */
  {
    stream_send_unit_array(*((t_stream_ptr)&client_DWork.StreamConnect_Stream),
      &client_B.SineWave, sizeof(real_T), 1);
  }

  /* S-Function (stream_flush_block): '<Root>/Stream Flush' incorporates:
   *  S-Function (stream_send_block): '<Root>/Stream Send'
   *  S-Function (stream_connect_block): '<Root>/Stream Connect'
   */
  /* S-Function Block: client/Stream Flush (stream_flush_block) */
  {
    t_error result;
    result = stream_flush(*((t_stream_ptr)((t_stream_ptr)&
      client_DWork.StreamConnect_Stream)));
    rtb_StreamFlush_o1 = ((t_stream_ptr)((t_stream_ptr)&
      client_DWork.StreamConnect_Stream));
    client_B.StreamFlush_o2 = (int32_T) result;
  }

  UNUSED_PARAMETER(tid);
}
Esempio n. 21
0
int stream_write_file (struct stream *stream, int fd, size_t *sizep)
{
    int err;

    if (!stream->type->sendfile)
        // fallback
        return _stream_write_file(stream, fd, sizep);

    // our write buffer must be empty, since sendfile will bypass it
    if ((err = stream_flush(stream)))
        return err;

    if ((err = stream->type->sendfile(fd, sizep, stream->ctx)))
        return err;

    return 0;
}
Esempio n. 22
0
  file_logger& operator<<(const char* a) {
    // get the stream buffer
    logger_impl::streambuff_tls_entry* streambufentry = reinterpret_cast<logger_impl::streambuff_tls_entry*>(
                                          pthread_getspecific(streambuffkey));
    if (streambufentry != NULL) {
      std::stringstream& streambuffer = streambufentry->streambuffer;
      bool& streamactive = streambufentry->streamactive;

      if (streamactive) {
        streambuffer << a;
        if (a[strlen(a)-1] == '\n') {
          stream_flush();
        }
      }
    }
    return *this;
  }
Esempio n. 23
0
static void
tcp_stream_flush (tcp_stream_t *u)
{
    tcp_socket_t*  s = u->socket;
	if (! s)
		return;
	mutex_lock (&s->lock);

	/* Flush output buffer. */
	if (u->outptr <= u->outdata) {
		mutex_unlock (&s->lock);
		return;
	}
	stream_flush (u);
	mutex_unlock (&s->lock);

	/* Force IP level to send a packet. */
	socket_flush (s);
}
Esempio n. 24
0
/**
 * cdk_stream_get_length: Return the length of the associated file handle.
 * @s: The STREAM object.
 *
 * This file only works for read stream because it's likely that the
 * write stream is not flushed or even no data was inserted.
 **/
unsigned
cdk_stream_get_length( cdk_stream_t s )
{
    struct stat statbuf;
    int rc;

    if( !s )
        return (unsigned)-1;
    
    rc = stream_flush( s );
    if( rc ) {
        s->error = CDK_File_Error;
        return (unsigned)-1;
    }
    if( fstat( fileno( s->fp ), &statbuf ) ) {
        s->error = CDK_File_Error;
        return (unsigned)-1;
    }
    return statbuf.st_size;
}
Esempio n. 25
0
int auth_login(struct config *config)
{
	struct stream *s;
	char hostbuf[MAXHOSTNAMELEN];
	char *login, *host;
	int error;

	s = config->server;
	error = gethostname(hostbuf, sizeof(hostbuf));
	hostbuf[sizeof(hostbuf) - 1] = '\0';
	if (error)
		host = NULL;
	else
		host = hostbuf;
	login = getlogin();
	proto_printf(s, "USER %s %s\n", login != NULL ? login : "******",
	    host != NULL ? host : "?");
	stream_flush(s);
	error = auth_domd5auth(config);
	return (error);
}
Esempio n. 26
0
int stream_vprintf (struct stream *stream, const char *fmt, va_list args)
{
    int ret, err;

    if ((ret = vsnprintf(stream_readbuf_ptr(stream), stream_readbuf_size(stream), fmt, args)) < 0) {
        log_perror("snprintf");
        return -1;
    }
    
    if (ret >= stream_readbuf_size(stream))
        // full
        return 1;
    
    stream_read_mark(stream, ret);
    
    // TODO: write buffering
    if ((err = stream_flush(stream)))
        return err;

    return 0;
}
Esempio n. 27
0
  inline file_logger& operator<<(std::ostream& (*f)(std::ostream&)){
    // get the stream buffer
    logger_impl::streambuff_tls_entry* streambufentry = reinterpret_cast<logger_impl::streambuff_tls_entry*>(
                                          pthread_getspecific(streambuffkey));
    if (streambufentry != NULL) {
      std::stringstream& streambuffer = streambufentry->streambuffer;
      bool& streamactive = streambufentry->streamactive;

      typedef std::ostream& (*endltype)(std::ostream&);
      if (streamactive) {
        if (endltype(f) == endltype(std::endl)) {
          streambuffer << "\n";
          stream_flush();
          if(streamloglevel == LOG_FATAL) {
            __print_back_trace();
            GRAPHLAB_LOGGER_FAIL_METHOD("LOG_FATAL encountered");
          }
        }
      }
    }
    return *this;
  }
Esempio n. 28
0
// Send UDP packet to wifi box,
// This function expect a code and a parameter
// The function tells the box what to do (Change color, on, off ...)
// The param tells gives the function some params
int SendUDP(int function, int param) {

  int i = 0;
  // Send every UDP command 3 times with an interval of 100ms
  // This way we are sure that the command reaches the wifi box
  do  {
    STREAM* Socket = stream_create("/dev/udp/IP-ADDRESS/8899/",0,0);
    if (Socket == NULL) {
      printf("Creating UDP socket failed");
      stream_close(Socket);
    }

    // Build the binary string to send
    char command[3]={function, param, 0x55 };

    stream_write(Socket,command,sizeof(command));
    stream_flush(Socket); stream_close(Socket);
    i = i + 1;
    sleep(100);
  } while (i < 3);
  return 1;
}
Esempio n. 29
0
  file_logger& operator<<(std::ostream& (*f)(std::ostream&)){
    // get the stream buffer
    logger_impl::streambuff_tls_entry* streambufentry = reinterpret_cast<logger_impl::streambuff_tls_entry*>(
                                          pthread_getspecific(streambuffkey));
    if (streambufentry != NULL) {
      std::stringstream& streambuffer = streambufentry->streambuffer;
      bool& streamactive = streambufentry->streamactive;

      typedef std::ostream& (*endltype)(std::ostream&);
      if (streamactive) {
        if (endltype(f) == endltype(std::endl)) {
          streambuffer << "\n";
          stream_flush();
          if(streamloglevel == LOG_FATAL) {
              throw "log fatal";
            // exit(EXIT_FAILURE);
          }
        }
      }
    }
    return *this;
  }
Esempio n. 30
0
cdk_error_t
cdk_stream_flush (cdk_stream_t s)
{
    cdk_error_t rc;

    if (!s)
    {
        gnutls_assert ();
        return CDK_Inv_Value;
    }

    /* The user callback does not support flush */
    if (s->cbs_hd)
        return 0;

    /* For read-only streams, no flush is needed. */
    if (!s->flags.write)
        return 0;

    if (!s->flags.filtrated)
    {
        if (!cdk_stream_get_length (s))
            return 0;
        rc = cdk_stream_seek (s, 0);
        if (!rc)
            rc = stream_flush (s);
        if (!rc)
            rc = stream_filter_write (s);
        s->flags.filtrated = 1;
        if (rc)
        {
            s->error = rc;
            gnutls_assert ();
            return rc;
        }
    }
    return 0;
}