static ssize_t qio_channel_websock_write_wire(QIOChannelWebsock *ioc, Error **errp) { ssize_t ret; ssize_t done = 0; qio_channel_websock_encode(ioc); while (ioc->encoutput.offset > 0) { ret = qio_channel_write(ioc->master, (char *)ioc->encoutput.buffer, ioc->encoutput.offset, errp); if (ret < 0) { if (ret == QIO_CHANNEL_ERR_BLOCK && done > 0) { return done; } else { return ret; } } buffer_advance(&ioc->encoutput, ret); done += ret; } return done; }
static gboolean qio_channel_websock_handshake_send(QIOChannel *ioc, GIOCondition condition, gpointer user_data) { QIOTask *task = user_data; QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK( qio_task_get_source(task)); Error *err = NULL; ssize_t ret; ret = qio_channel_write(wioc->master, (char *)wioc->encoutput.buffer, wioc->encoutput.offset, &err); if (ret < 0) { trace_qio_channel_websock_handshake_fail(ioc); qio_task_abort(task, err); error_free(err); return FALSE; } buffer_advance(&wioc->encoutput, ret); if (wioc->encoutput.offset == 0) { trace_qio_channel_websock_handshake_complete(ioc); qio_task_complete(task); return FALSE; } trace_qio_channel_websock_handshake_pending(ioc, G_IO_OUT); return TRUE; }
static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc, GIOCondition cond G_GNUC_UNUSED, gpointer user_data) { TCPChardevTelnetInit *init = user_data; ssize_t ret; ret = qio_channel_write(ioc, init->buf, init->buflen, NULL); if (ret < 0) { if (ret == QIO_CHANNEL_ERR_BLOCK) { ret = 0; } else { tcp_chr_disconnect(init->chr); return FALSE; } } init->buflen -= ret; if (init->buflen == 0) { tcp_chr_connect(init->chr); return FALSE; } memmove(init->buf, init->buf + ret, init->buflen); return TRUE; }
/* Called with chr_write_lock held. */ static int udp_chr_write(Chardev *chr, const uint8_t *buf, int len) { UdpChardev *s = UDP_CHARDEV(chr); return qio_channel_write( s->ioc, (const char *)buf, len, NULL); }
static ssize_t qio_channel_tls_write_handler(const char *buf, size_t len, void *opaque) { QIOChannelTLS *tioc = QIO_CHANNEL_TLS(opaque); ssize_t ret; ret = qio_channel_write(tioc->master, buf, len, NULL); if (ret == QIO_CHANNEL_ERR_BLOCK) { errno = EAGAIN; return -1; } else if (ret < 0) { errno = EIO; return -1; } return ret; }
// unbounded_channels <= 0 means no, > 0 means yes // -1 means advance. void check_channel(char threadsafe, qio_chtype_t type, int64_t start, int64_t len, int64_t chunksz, qio_hint_t file_hints, qio_hint_t ch_hints, char unbounded_channels, char reopen) { qio_file_t* f; qio_channel_t* writing; qio_channel_t* reading; int64_t offset; int64_t usesz; int64_t end = start + len; int err; unsigned char* chunk; unsigned char* got_chunk; int64_t k; ssize_t amt_written; ssize_t amt_read; char* chhints; char* fhints; FILE* writefp = NULL; FILE* readfp = NULL; int memory; int64_t ch_end = end; char filename[128]; int fd = -1; strcpy(filename,"/tmp/qio_testXXXXXX"); if( unbounded_channels > 0 ) ch_end = INT64_MAX; ch_hints = (ch_hints & ~ QIO_CHTYPEMASK) | type; memory = 0; if( (file_hints & QIO_METHODMASK) == QIO_METHOD_MEMORY || (ch_hints & QIO_METHODMASK) == QIO_METHOD_MEMORY ) { memory = 1; } if( memory ) { file_hints = (file_hints & ~ QIO_METHODMASK ) | QIO_METHOD_MEMORY; ch_hints = (ch_hints & ~ QIO_METHODMASK ) | QIO_METHOD_MEMORY; } if( memory && type == QIO_CH_ALWAYS_UNBUFFERED ) return; if( memory && reopen ) return; if( (ch_hints & QIO_METHODMASK) == QIO_METHOD_FREADFWRITE ) { if( (file_hints & QIO_METHODMASK) != QIO_METHOD_FREADFWRITE ) return; } if( (ch_hints & QIO_METHODMASK) == QIO_METHOD_MMAP ) { if( (file_hints & QIO_METHODMASK) != QIO_METHOD_MMAP ) return; } fhints = qio_hints_to_string(file_hints); chhints = qio_hints_to_string(ch_hints); printf("check_channel(threadsafe=%i, type=%i, start=%lli, len=%lli, chunksz=%lli, file_hints=%s, ch_hints=%s, unbounded=%i, reopen=%i)\n", (int) threadsafe, (int) type, (long long int) start, (long long int) len, (long long int) chunksz, fhints, chhints, (int) unbounded_channels, (int) reopen ); free(fhints); free(chhints); chunk = malloc(chunksz); got_chunk = malloc(chunksz); assert(chunk); assert(got_chunk); if( memory ) { err = qio_file_open_mem_ext(&f, NULL, QIO_FDFLAG_READABLE|QIO_FDFLAG_WRITEABLE|QIO_FDFLAG_SEEKABLE, file_hints, NULL); assert(!err); } else { // Open a temporary file. if( reopen ) { fd = mkstemp(filename); close(fd); err = qio_file_open_access(&f, filename, "w", file_hints, NULL); assert(!err); } else { err = qio_file_open_tmp(&f, file_hints, NULL); assert(!err); } // Rewind the file if (f->fp ) { int got; got = fseek(f->fp, start, SEEK_SET); assert( got == 0 ); } else { off_t off; err = sys_lseek(f->fd, start, SEEK_SET, &off); assert(!err); } } // Create a "write to file" channel. err = qio_channel_create(&writing, f, ch_hints, 0, 1, start, ch_end, NULL); assert(!err); // Write stuff to the file. for( offset = start; offset < end; offset += usesz ) { usesz = chunksz; if( offset + usesz > end ) usesz = end - offset; // Fill chunk. fill_testdata(offset, usesz, chunk); // Write chunk. if( writefp ) { amt_written = fwrite(chunk, 1, usesz, writefp); } else { err = qio_channel_write(threadsafe, writing, chunk, usesz, &amt_written); assert(!err); } assert(amt_written == usesz); } // Attempt to write 1 more byte; we should get EEOF // if we've restricted the range of the channel. // Write chunk. if( unbounded_channels > 0) { // do nothing } else { if( writefp ) { int got; got = fflush(writefp); assert(got == 0); amt_written = fwrite(chunk, 1, 1, writefp); // fwrite might buffer on its own. if( amt_written != 0 ) { got = fflush(writefp); assert(got == EOF); } assert(errno == EEOF); } else { if( unbounded_channels < 0 ) { int times = -unbounded_channels; for( int z = 0; z < times; z++ ) { err = qio_channel_advance(threadsafe, writing, 1); assert( !err ); } } err = qio_channel_write(threadsafe, writing, chunk, 1, &amt_written); assert(amt_written == 0); assert( err == EEOF ); } } qio_channel_release(writing); // Reopen the file if we're doing reopen if( reopen ) { // Close the file. qio_file_release(f); err = qio_file_open_access(&f, filename, "r", file_hints, NULL); assert(!err); } // Check that the file is the right length. if( !memory ) { struct stat stats; err = sys_fstat(f->fd, &stats); assert(!err); assert(stats.st_size == end); } // That was fun. Now start at the beginning of the file // and read the data. // Rewind the file if( !memory ) { off_t off; sys_lseek(f->fd, start, SEEK_SET, &off); assert(!err); } // Read the data. //err = qio_channel_init_file(&reading, type, f, ch_hints, 1, 0, start, end); err = qio_channel_create(&reading, f, ch_hints, 1, 0, start, ch_end, NULL); assert(!err); // Read stuff from the file. for( offset = start; offset < end; offset += usesz ) { usesz = chunksz; if( offset + usesz > end ) usesz = end - offset; // Fill chunk. fill_testdata(offset, usesz, chunk); memset(got_chunk, 0xff, usesz); // Read chunk. if( readfp ) { amt_read = fread(got_chunk, 1, usesz, readfp); } else { err = qio_channel_read(threadsafe, reading, got_chunk, usesz, &amt_read); assert( err == EEOF || err == 0); } assert(amt_read == usesz); // Compare chunk. for( k = 0; k < usesz; k++ ) { assert(got_chunk[k] == chunk[k]); } } if( readfp ) { amt_read = fread(got_chunk, 1, 1, readfp); assert( amt_read == 0 ); assert( feof(readfp) ); } else { if( unbounded_channels < 0 ) { int times = -unbounded_channels; for( int z = 0; z < times; z++ ) { err = qio_channel_advance(threadsafe, reading, 1); assert( !err ); } err = qio_channel_advance(threadsafe, reading, -unbounded_channels); assert( !err ); } err = qio_channel_read(threadsafe, reading, got_chunk, 1, &amt_read); assert( err == EEOF ); } qio_channel_release(reading); //err = qio_channel_destroy(&reading); // Close the file. qio_file_release(f); if( reopen ) { unlink(filename); } free(chunk); free(got_chunk); }