int mongoc_stream_tls_openssl_bio_read (BIO *b, char *buf, int len) { mongoc_stream_tls_t *tls; int ret; BSON_ASSERT (b); BSON_ASSERT (buf); ENTRY; tls = (mongoc_stream_tls_t *) BIO_get_data (b); if (!tls) { RETURN (-1); } errno = 0; ret = (int) mongoc_stream_read ( tls->base_stream, buf, len, 0, tls->timeout_msec); BIO_clear_retry_flags (b); if ((ret <= 0) && MONGOC_ERRNO_IS_AGAIN (errno)) { BIO_set_retry_read (b); } RETURN (ret); }
static int _mongoc_stream_tls_bio_read (BIO *b, char *buf, int len) { mongoc_stream_tls_t *tls; int ret; BSON_ASSERT (b); BSON_ASSERT (buf); if (!(tls = b->ptr)) { return -1; } errno = 0; ret = (int)mongoc_stream_read (tls->base_stream, buf, len, 0, tls->timeout_msec); BIO_clear_retry_flags (b); if ((ret < 0) && MONGOC_ERRNO_IS_AGAIN (errno)) { BIO_set_retry_read (b); } return ret; }
/** * mongoc_buffer_append_from_stream: * @buffer; A mongoc_buffer_t. * @stream: The stream to read from. * @size: The number of bytes to read. * @timeout_msec: The number of milliseconds to wait or -1 for the default * @error: A location for a bson_error_t, or NULL. * * Reads from stream @size bytes and stores them in @buffer. This can be used * in conjunction with reading RPCs from a stream. You read from the stream * into this buffer and then scatter the buffer into the RPC. * * Returns: true if successful; otherwise false and @error is set. */ bool _mongoc_buffer_append_from_stream (mongoc_buffer_t *buffer, mongoc_stream_t *stream, size_t size, int32_t timeout_msec, bson_error_t *error) { uint8_t *buf; ssize_t ret; ENTRY; BSON_ASSERT (buffer); BSON_ASSERT (stream); BSON_ASSERT (size); BSON_ASSERT (buffer->datalen); BSON_ASSERT ((buffer->datalen + size) < INT_MAX); if (!SPACE_FOR (buffer, size)) { if (buffer->len) { memmove (&buffer->data[0], &buffer->data[buffer->off], buffer->len); } buffer->off = 0; if (!SPACE_FOR (buffer, size)) { buffer->datalen = bson_next_power_of_two (size + buffer->len + buffer->off); buffer->data = (uint8_t *) buffer->realloc_func ( buffer->data, buffer->datalen, NULL); } } buf = &buffer->data[buffer->off + buffer->len]; BSON_ASSERT ((buffer->off + buffer->len + size) <= buffer->datalen); ret = mongoc_stream_read (stream, buf, size, size, timeout_msec); if (ret != size) { bson_set_error (error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "Failed to read %" PRIu64 " bytes: socket error or timeout", (uint64_t) size); RETURN (false); } buffer->len += ret; RETURN (true); }
/** * mongoc_buffer_append_from_stream: * @buffer; A mongoc_buffer_t. * @stream: The stream to read from. * @size: The number of bytes to read. * @timeout_msec: The number of milliseconds to wait or -1 for the default * @error: A location for a bson_error_t, or NULL. * * Reads from stream @size bytes and stores them in @buffer. This can be used * in conjunction with reading RPCs from a stream. You read from the stream * into this buffer and then scatter the buffer into the RPC. * * Returns: true if successful; otherwise false and @error is set. */ bool _mongoc_buffer_append_from_stream (mongoc_buffer_t *buffer, mongoc_stream_t *stream, size_t size, int32_t timeout_msec, bson_error_t *error) { uint8_t *buf; ssize_t ret; ENTRY; bson_return_val_if_fail (buffer, false); bson_return_val_if_fail (stream, false); bson_return_val_if_fail (size, false); BSON_ASSERT (buffer->datalen); if (!SPACE_FOR (buffer, size)) { if (buffer->len) { memmove(&buffer->data[0], &buffer->data[buffer->off], buffer->len); } buffer->off = 0; if (!SPACE_FOR (buffer, size)) { buffer->datalen = bson_next_power_of_two ((uint32_t)size); buffer->data = buffer->realloc_func (buffer->data, buffer->datalen, NULL); } } buf = &buffer->data[buffer->off + buffer->len]; ret = mongoc_stream_read (stream, buf, size, size, timeout_msec); if (ret != size) { bson_set_error (error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "Failed to read %u bytes from socket.", (unsigned)size); RETURN (false); } buffer->len += ret; RETURN (true); }
/** * mongoc_buffer_try_append_from_stream: * @buffer; A mongoc_buffer_t. * @stream: The stream to read from. * @size: The number of bytes to read. * @timeout_msec: The number of milliseconds to wait or -1 for the default * @error: A location for a bson_error_t, or NULL. * * Reads from stream @size bytes and stores them in @buffer. This can be used * in conjunction with reading RPCs from a stream. You read from the stream * into this buffer and then scatter the buffer into the RPC. * * Returns: bytes read if successful; otherwise -1 and @error is set. */ ssize_t _mongoc_buffer_try_append_from_stream (mongoc_buffer_t *buffer, mongoc_stream_t *stream, size_t size, int32_t timeout_msec, bson_error_t *error) { uint8_t *buf; ssize_t ret; ENTRY; BSON_ASSERT (buffer); BSON_ASSERT (stream); BSON_ASSERT (size); BSON_ASSERT (buffer->datalen); BSON_ASSERT ((buffer->datalen + size) < INT_MAX); if (!SPACE_FOR (buffer, size)) { if (buffer->len) { memmove (&buffer->data[0], &buffer->data[buffer->off], buffer->len); } buffer->off = 0; if (!SPACE_FOR (buffer, size)) { buffer->datalen = bson_next_power_of_two (size + buffer->len + buffer->off); buffer->data = (uint8_t *) buffer->realloc_func ( buffer->data, buffer->datalen, NULL); } } buf = &buffer->data[buffer->off + buffer->len]; BSON_ASSERT ((buffer->off + buffer->len + size) <= buffer->datalen); ret = mongoc_stream_read (stream, buf, size, 0, timeout_msec); if (ret > 0) { buffer->len += ret; } RETURN (ret); }
/** create a gridfs file from a stream * * The stream is fully consumed in creating the file */ mongoc_gridfs_file_t * mongoc_gridfs_create_file_from_stream (mongoc_gridfs_t *gridfs, mongoc_stream_t *stream, mongoc_gridfs_file_opt_t *opt) { mongoc_gridfs_file_t *file; ssize_t r; uint8_t buf[MONGOC_GRIDFS_STREAM_CHUNK]; mongoc_iovec_t iov; int timeout; ENTRY; BSON_ASSERT (gridfs); BSON_ASSERT (stream); iov.iov_base = (void *)buf; iov.iov_len = 0; file = _mongoc_gridfs_file_new (gridfs, opt); timeout = gridfs->client->cluster.sockettimeoutms; for (;; ) { r = mongoc_stream_read (stream, iov.iov_base, MONGOC_GRIDFS_STREAM_CHUNK, 0, timeout); if (r > 0) { iov.iov_len = r; mongoc_gridfs_file_writev (file, &iov, 1, timeout); } else if (r == 0) { break; } else { mongoc_gridfs_file_destroy (file); RETURN (NULL); } } mongoc_stream_failed (stream); mongoc_gridfs_file_seek (file, 0, SEEK_SET); RETURN (file); }
OSStatus mongoc_secure_transport_read (SSLConnectionRef connection, void *data, size_t *data_length) { mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *)connection; ssize_t length; ENTRY; errno = 0; /* 4 arguments is *min_bytes* -- This is not a negotiation. * Secure Transport wants all or nothing. We must continue reading until * we get this amount, or timeout */ length = mongoc_stream_read (tls->base_stream, data, *data_length, *data_length, tls->timeout_msec); if (length > 0) { *data_length = length; RETURN(noErr); } if (length == 0) { RETURN(errSSLClosedGraceful); } switch (errno) { case ENOENT: RETURN(errSSLClosedGraceful); break; case ECONNRESET: RETURN(errSSLClosedAbort); break; case EAGAIN: RETURN(errSSLWouldBlock); break; default: RETURN(-36); /* ioErr */ break; } }
/** create a gridfs file from a stream * * The stream is fully consumed in creating the file */ mongoc_gridfs_file_t * mongoc_gridfs_create_file_from_stream (mongoc_gridfs_t *gridfs, mongoc_stream_t *stream, mongoc_gridfs_file_opt_t *opt) { mongoc_gridfs_file_t *file; ssize_t r; bson_uint8_t buf[MONGOC_GRIDFS_STREAM_CHUNK]; struct iovec iov = { buf, 0 }; ENTRY; BSON_ASSERT (gridfs); BSON_ASSERT (stream); file = _mongoc_gridfs_file_new (gridfs, opt); for (;; ) { r = mongoc_stream_read (stream, iov.iov_base, MONGOC_GRIDFS_STREAM_CHUNK, 0, 0); if (r > 0) { iov.iov_len = r; mongoc_gridfs_file_writev (file, &iov, 1, 0); } else if (r == 0) { break; } else { mongoc_gridfs_file_destroy (file); RETURN (NULL); } } mongoc_stream_destroy (stream); mongoc_gridfs_file_seek (file, 0, SEEK_SET); RETURN (file); }
/** * _mongoc_buffer_fill: * @buffer: A mongoc_buffer_t. * @stream: A stream to read from. * @min_bytes: The minumum number of bytes to read. * @error: A location for a bson_error_t or NULL. * * Attempts to fill the entire buffer, or at least @min_bytes. * * Returns: The number of buffered bytes, or -1 on failure. */ ssize_t _mongoc_buffer_fill (mongoc_buffer_t *buffer, mongoc_stream_t *stream, size_t min_bytes, int32_t timeout_msec, bson_error_t *error) { ssize_t ret; size_t avail_bytes; ENTRY; bson_return_val_if_fail(buffer, false); bson_return_val_if_fail(stream, false); bson_return_val_if_fail(min_bytes >= 0, false); BSON_ASSERT (buffer->data); BSON_ASSERT (buffer->datalen); if (min_bytes <= buffer->len) { RETURN (buffer->len); } min_bytes -= buffer->len; if (buffer->len) { memmove (&buffer->data[0], &buffer->data[buffer->off], buffer->len); } buffer->off = 0; if (!SPACE_FOR (buffer, min_bytes)) { buffer->datalen = bson_next_power_of_two (buffer->len + min_bytes); buffer->data = buffer->realloc_func (buffer->data, buffer->datalen, buffer->realloc_data); } avail_bytes = buffer->datalen - buffer->len; ret = mongoc_stream_read (stream, &buffer->data[buffer->off + buffer->len], avail_bytes, min_bytes, timeout_msec); if (ret == -1) { bson_set_error (error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "Failed to buffer %u bytes within %d milliseconds.", (unsigned)min_bytes, (int)timeout_msec); RETURN (-1); } buffer->len += ret; if (buffer->len < min_bytes) { bson_set_error (error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "Could only buffer %u of %u bytes in %d milliseconds.", (unsigned)buffer->len, (unsigned)min_bytes, (int)timeout_msec); RETURN (-1); } RETURN (buffer->len); }
static void validate (const char *name) /* IN */ { mongoc_stream_t *stream; mongoc_rpc_t rpc; #ifdef _WIN32 struct _stat st; #else struct stat st; #endif uint8_t *buf; int32_t len; int ret; stream = mongoc_stream_file_new_for_path (name, O_RDONLY, 0); if (!stream) { perror ("failed to open file"); exit (EXIT_FAILURE); } #ifdef _WIN32 ret = _stat (name, &st); #else ret = stat (name, &st); #endif if (ret != 0) { perror ("failed to stat() file."); exit (EXIT_FAILURE); } if ((st.st_size > (100 * 1024 * 1024)) || (st.st_size < 16)) { fprintf (stderr, "%s: unreasonable message size\n", name); exit (EXIT_FAILURE); } buf = malloc (st.st_size); if (buf == NULL) { fprintf (stderr, "%s: Failed to malloc %d bytes.\n", name, (int)st.st_size); exit (EXIT_FAILURE); } if (st.st_size != mongoc_stream_read (stream, buf, st.st_size, st.st_size, -1)) { fprintf (stderr, "%s: Failed to read %d bytes into buffer.\n", name, (int)st.st_size); exit (EXIT_FAILURE); } memcpy (&len, buf, 4); len = BSON_UINT32_FROM_LE (len); if (len != st.st_size) { fprintf (stderr, "%s is invalid. Invalid Length.\n", name); exit (EXIT_FAILURE); } if (!_mongoc_rpc_scatter (&rpc, buf, st.st_size)) { fprintf (stderr, "%s is invalid. Invalid Format.\n", name); exit (EXIT_FAILURE); } fprintf (stdout, "%s is valid.\n", name); bson_free (buf); }