globus_result_t
globus_i_xio_system_try_readv(
    globus_xio_system_file_t            fd,
    const globus_xio_iovec_t *          iov,
    int                                 iovc,
    globus_size_t *                     nbytes)
{
    globus_ssize_t                      rc;
    globus_result_t                     result;
    GlobusXIOName(globus_i_xio_system_try_readv);

    GlobusXIOSystemDebugEnterFD(fd);

    do
    {
#ifdef HAVE_READV
        rc = readv(fd, iov,
                (iovc > globus_l_xio_iov_max) ? globus_l_xio_iov_max : iovc);
#else
        rc = read(fd, iov[0].iov_base,iov[0].iov_len);
#endif
        GlobusXIOSystemUpdateErrno();
    } while(rc < 0 && errno == EINTR);

    if(rc < 0)
    {
        if(GlobusLXIOSystemWouldBlock(errno))
        {
            rc = 0;
        }
        else
        {
            result = GlobusXIOErrorSystemError("readv", errno);
            goto error_errno;
        }
    }
    else if(rc == 0)
    {
        result = GlobusXIOErrorEOF();
        goto error_eof;
    }

    *nbytes = rc;

    GlobusXIOSystemDebugPrintf(
        GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
        ("[%s] Read %d bytes\n", _xio_name, rc));

    GlobusXIOSystemDebugRawIovec(rc, iov);

    GlobusXIOSystemDebugExitFD(fd);
    return GLOBUS_SUCCESS;

error_errno:
error_eof:
    *nbytes = 0;
    GlobusXIOSystemDebugExitWithErrorFD(fd);
    return result;
}
globus_result_t
globus_i_xio_system_try_recv(
    globus_xio_system_socket_t          fd,
    void *                              buf,
    globus_size_t                       buflen,
    int                                 flags,
    globus_size_t *                     nbytes)
{
    globus_ssize_t                      rc = 0;
    globus_result_t                     result;
    GlobusXIOName(globus_i_xio_system_try_recv);

    GlobusXIOSystemDebugEnterFD(fd);

    if(buflen)
    {
        do
        {
            rc = recv(fd, buf, buflen, flags);
            GlobusXIOSystemUpdateErrno();
        } while(rc < 0 && errno == EINTR);

        if(rc < 0)
        {
            if(GlobusLXIOSystemWouldBlock(errno))
            {
                rc = 0;
            }
            else
            {
                result = GlobusXIOErrorSystemError("recv", errno);
                goto error_errno;
            }
        }
        else if(rc == 0)
        {
            result = GlobusXIOErrorEOF();
            goto error_eof;
        }

        GlobusXIOSystemDebugPrintf(
            GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
            ("[%s] Read %d bytes\n", _xio_name, rc));

        GlobusXIOSystemDebugRawBuffer(rc, buf);
    }

    *nbytes = rc;

    GlobusXIOSystemDebugExitFD(fd);
    return GLOBUS_SUCCESS;

error_errno:
error_eof:
    *nbytes = 0;
    GlobusXIOSystemDebugExitWithErrorFD(fd);
    return result;
}
globus_result_t
globus_i_xio_system_try_read(
    globus_xio_system_file_t            fd,
    void *                              buf,
    globus_size_t                       buflen,
    globus_size_t *                     nbytes)
{
    globus_ssize_t                      rc = 0;
    globus_result_t                     result;
    GlobusXIOName(globus_i_xio_system_try_read);

    GlobusXIOSystemDebugEnterFD(fd);

    /* calls to this with buflen == 0 are requesting select only */
    if(buflen)
    {
        do
        {
            rc = read(fd, buf, buflen);
            GlobusXIOSystemUpdateErrno();
        } while(rc < 0 && errno == EINTR);

        if(rc < 0)
        {
            if(GlobusLXIOSystemWouldBlock(errno))
            {
                rc = 0;
            }
            else
            {
                result = GlobusXIOErrorSystemError("read", errno);
                goto error_errno;
            }
        }
        else if(rc == 0) /* what about UDP? */
        {
            result = GlobusXIOErrorEOF();
            goto error_eof;
        }

        GlobusXIOSystemDebugPrintf(
            GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
            ("[%s] Read %d bytes (buflen = %d)\n", _xio_name, rc, buflen));

        GlobusXIOSystemDebugRawBuffer(rc, buf);
    }

    *nbytes = rc;

    GlobusXIOSystemDebugExitFD(fd);
    return GLOBUS_SUCCESS;

error_errno:
error_eof:
    *nbytes = 0;
    GlobusXIOSystemDebugExitWithErrorFD(fd);
    return result;
}
Esempio n. 4
0
static
globus_result_t
globus_l_xio_test_write_buffer(
    globus_xio_handle_t                 handle,
    globus_byte_t *                     message,
    globus_size_t                       message_size,
    globus_size_t                       buffer_size)
{
    globus_byte_t *                     ptr = message;
    globus_size_t                       left = message_size;
    globus_size_t                       to_write;
    globus_size_t                       nbytes;
    globus_result_t                     result = GLOBUS_SUCCESS;
    GlobusXIOName(globus_l_xio_test_write_buffer);

    if (buffer_size == 0)
    {
        buffer_size = 1024;
    }
    while ((left > 0) && (result == GLOBUS_SUCCESS))
    {
        to_write = (left > buffer_size) ? buffer_size : left;
        result = globus_xio_write(
                handle,
                ptr,
                to_write,
                to_write,
                &nbytes,
                NULL);

        if (result == GLOBUS_SUCCESS)
        {
            if (nbytes != to_write)
            {
                fprintf(stderr, "Didn't write all I expected.\n");
                result = GlobusXIOErrorEOF();
            }
            left -= nbytes;
            ptr += nbytes;
        }
        else
        {
            fprintf(stderr, "Error writing data: %s\n",
                    globus_object_printable_to_string(globus_error_peek(result)));
        }
    }

    globus_xio_handle_cntl(
            handle,
            http_driver,
            GLOBUS_XIO_HTTP_HANDLE_SET_END_OF_ENTITY);

    return result;
}
static
globus_result_t
globus_l_xio_test_write_buffer(
    globus_xio_handle_t                 handle,
    globus_byte_t *                     msg,
    globus_size_t                       msg_size,
    globus_xio_driver_t			http_driver)
{
    globus_size_t                       nbytes;
    globus_result_t                     result;
    GlobusXIOName(globus_l_xio_test_write_buffer);

    result = globus_xio_write(
	    handle,
	    msg,
	    msg_size,
	    msg_size,
	    &nbytes,
	    NULL);

    if (result == GLOBUS_SUCCESS)
    {
	if (nbytes != msg_size)
	{
	    fprintf(stderr, "Didn't write all I expected.\n");
	    result = GlobusXIOErrorEOF();
	}
    }
    else
    {
	fprintf(stderr, "Error writing data: %s\n",
		globus_object_printable_to_string(globus_error_peek(result)));
    }

    globus_xio_handle_cntl(
            handle,
            http_driver,
            GLOBUS_XIO_HTTP_HANDLE_SET_END_OF_ENTITY);

    return result;
}
void
globus_i_xio_http_server_read_request_callback(
    globus_xio_operation_t              op,
    globus_result_t                     result,
    globus_size_t                       nbytes,
    void *                              user_arg)
{
    globus_i_xio_http_handle_t *        http_handle = user_arg;
    globus_bool_t                       done;
    globus_result_t                     eof_result = GLOBUS_SUCCESS;
    globus_i_xio_http_attr_t *          descriptor;
    globus_bool_t                       registered_again = GLOBUS_FALSE;
    GlobusXIOName(globus_i_xio_http_server_read_request_callback);

    globus_mutex_lock(&http_handle->mutex);

    if (result != GLOBUS_SUCCESS)
    {
        if (globus_xio_error_is_eof(result))
        {
            eof_result = result;
        }
        else
        {
            goto error_exit;
        }
    }

    /* Haven't parsed request and headers yet */
    http_handle->read_buffer_valid += nbytes;

    result = globus_l_xio_http_server_parse_request(http_handle, &done);
    if (result == GLOBUS_SUCCESS && !done)
    {
        goto reregister_read;
    }
    else if (result != GLOBUS_SUCCESS)
    {
        goto error_exit;
    }

    /* Determine whether we should expect an entity along with the
     * request
     */
    if ((http_handle->request_info.http_version == GLOBUS_XIO_HTTP_VERSION_1_1)
            && (http_handle->request_info.headers.transfer_encoding
            == GLOBUS_XIO_HTTP_TRANSFER_ENCODING_CHUNKED))
    {
        http_handle->parse_state = GLOBUS_XIO_HTTP_CHUNK_LINE;
    }
    else if (GLOBUS_I_XIO_HTTP_HEADER_IS_CONTENT_LENGTH_SET(
                &http_handle->request_info.headers))
    {
        http_handle->parse_state = GLOBUS_XIO_HTTP_IDENTITY_BODY;
    }

    if (GLOBUS_I_XIO_HTTP_HEADER_IS_CONNECTION_CLOSE(
                &http_handle->request_info.headers))
    {
        http_handle->response_info.headers.flags |=
                GLOBUS_I_XIO_HTTP_HEADER_CONNECTION_CLOSE;
    }

    http_handle->send_state = GLOBUS_XIO_HTTP_STATUS_LINE;

    descriptor = globus_xio_operation_get_data_descriptor(op, GLOBUS_TRUE);
    if (descriptor == NULL)
    {
        result = GlobusXIOErrorMemory("descriptor");
        
        goto error_exit;
    }
    globus_i_xio_http_request_destroy(&descriptor->request);
    result = globus_i_xio_http_request_copy(
            &descriptor->request,
            &http_handle->request_info);
    if (result != GLOBUS_SUCCESS)
    {
        goto error_exit;
    }

    result = globus_i_xio_http_parse_residue(http_handle, &registered_again);

    if ((http_handle->read_operation.wait_for <= 0 && !registered_again) ||
        result != GLOBUS_SUCCESS)
    {
        if (http_handle->response_info.headers.transfer_encoding !=
                GLOBUS_XIO_HTTP_TRANSFER_ENCODING_CHUNKED &&
            GLOBUS_I_XIO_HTTP_HEADER_IS_CONTENT_LENGTH_SET(
                    &http_handle->response_info.headers) &&
            http_handle->response_info.headers.content_length == 0)
        {
            /* Synthesize EOF if we've read all of the entity content */
            result = GlobusXIOErrorEOF();
        }
        /*
         * Either we've read enough, hit end of chunk, no entity was present,
         * or pass to transport failed. Call finished_read
         */
        nbytes = http_handle->read_operation.nbytes;
        globus_libc_free(http_handle->read_operation.iov);
        http_handle->read_operation.iov = NULL;
        http_handle->read_operation.iovcnt = 0;
        http_handle->read_operation.operation = NULL;
        http_handle->read_operation.driver_handle = NULL;
        http_handle->read_operation.nbytes = 0;

        globus_mutex_unlock(&http_handle->mutex);
        
        globus_xio_driver_finished_read(op, result, nbytes);

        return;
    }
    else if (registered_again)
    {
        globus_mutex_unlock(&http_handle->mutex);
        return;
    }

    /* FALLSTHROUGH */
reregister_read:
    globus_assert(op == http_handle->read_operation.operation);
    if (eof_result != GLOBUS_SUCCESS)
    {
        /* Header block wasn't complete before eof */
        result = eof_result;
        goto error_exit;
    }
    result = globus_i_xio_http_clean_read_buffer(http_handle);

    if (result != GLOBUS_SUCCESS)
    {
        goto error_exit;
    }

    result = globus_xio_driver_pass_read(
            op,
            &http_handle->read_iovec,
            1,
            1,
            globus_i_xio_http_server_read_request_callback,
            http_handle);

    if (result != GLOBUS_SUCCESS)
    {
        goto error_exit;
    }

    globus_mutex_unlock(&http_handle->mutex);
    return;

error_exit:
    globus_libc_free(http_handle->read_operation.iov);
    http_handle->read_operation.iov = NULL;
    http_handle->read_operation.iovcnt = 0;
    http_handle->read_operation.operation = NULL;
    http_handle->read_operation.driver_handle = NULL;
    http_handle->read_operation.nbytes = 0;
    globus_mutex_unlock(&http_handle->mutex);

    globus_xio_driver_finished_read(op, result, 0);
}
globus_result_t
globus_i_xio_system_try_recvmsg(
    globus_xio_system_socket_t          fd,
    struct msghdr *                     msghdr,
    int                                 flags,
    globus_size_t *                     nbytes)
{
    globus_ssize_t                      rc;
    globus_result_t                     result;
    GlobusXIOName(globus_i_xio_system_try_recvmsg);

    GlobusXIOSystemDebugEnterFD(fd);

#ifdef WIN32
    {
        DWORD                           received = 0;
        DWORD                           oflags = flags;
        INT                             size = msghdr->msg_namelen;

        rc = WSARecvFrom(
            fd,
            (WSABUF *) msghdr->msg_iov,
            msghdr->msg_iovlen,
            &received,
            &oflags,
            msghdr->msg_name,
            &size,
            0,
            0);
        if(rc != 0)
        {
            GlobusXIOSystemUpdateErrno();
            rc = -1;
        }
        else
        {
            rc = received;
        }
    }
#elif defined(HAVE_RECVSMSG)
    {
        globus_size_t                   orig_iovc;

        orig_iovc = msghdr->msg_iovlen;
        msghdr->msg_iovlen = (orig_iovc > globus_l_xio_iov_max)
                ?  globus_l_xio_iov_max : orig_iovc;

        do
        {
            rc = recvmsg(fd, msghdr, flags);
            GlobusXIOSystemUpdateErrno();
        } while(rc < 0 && errno == EINTR);

        msghdr->msg_iovlen = orig_iovc;
    }
#else
    {
        /* XXX this is not an acceptable work around for udp sockets */
        do
        {
            if (msghdr->msg_name)
            {
                rc = recvfrom(
                        fd,
                        msghdr->msg_iov[0].iov_base,
                        msghdr->msg_iov[0].iov_len,
                        flags,
                        (struct sockaddr *) msghdr->msg_name,
                        &msghdr->msg_namelen);
            }
            else
            {
                rc = recv(
                        fd,
                        msghdr->msg_iov[0].iov_base,
                        msghdr->msg_iov[1].iov_len,
                        flags);
            }

            GlobusXIOSystemUpdateErrno();
        } while(rc < 0 && errno == EINTR);
    }
#endif

    if(rc < 0)
    {
        if(GlobusLXIOSystemWouldBlock(errno))
        {
            rc = 0;
        }
        else
        {
            result = GlobusXIOErrorSystemError("recvmsg", errno);
            goto error_errno;
        }
    }
    else if(rc == 0)
    {
        result = GlobusXIOErrorEOF();
        goto error_eof;
    }

    *nbytes = rc;

    GlobusXIOSystemDebugPrintf(
        GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
        ("[%s] Read %d bytes\n", _xio_name, rc));

    GlobusXIOSystemDebugRawIovec(rc, msghdr->msg_iov);

    GlobusXIOSystemDebugExitFD(fd);
    return GLOBUS_SUCCESS;

error_errno:
error_eof:
    *nbytes = 0;
    GlobusXIOSystemDebugExitWithErrorFD(fd);
    return result;
}