* A transport driver is one that is responsible for
* data communication. For example, a TCP or UDP driver would
* transmit data via network sockets, or a file driver would write
* data to a file.
*
* There must be exactly one transport driver in a stack, at its bottom.
* A transport driver never passes an operation to another driver in
* the stack. Instead, this type of driver relies on globus_xio system
* functions to implement data operations.
*
*
*
Transform driver:
*
* A transform driver is any intermediate driver in the stack. A transform
* driver relies on some other drivers on the driver stack to
* perform the data transport operation. An example of a transform driver
* would one which implements a network protocol such as http. This driver
* would frame and parse messages, but would rely on other drivers in
* the XIO stack.
*
* This allows additional transforms to happen in the XIO stack, such as
* layering the http protocol on top of an SSL protocol driver before
* transmitting the data via TCP.
*
*
*
* @section driver_api Driver API
* The Globus XIO Driver API is a set of functions and interfaces
* to allow a developer to create an XIO driver.
* To create a driver the user must implement all of the interface
* functions in the driver specification.
* There is also a set of functions provided to assist the driver
* author in implementing a driver.
*
* @subsection driver_api_quickstart Quick Start
* For basic driver needs, the developer will have to pay attention to a
* few structures and concepts.
*
*
*
globus_xio_operation_t
*
* This structure represents a request for an operation. If
* the driver can service the operation it does so and the
* calls the appropriate finished function. If the
* driver cannot completely service the operation it can pass
* it to the next driver in the stack. As soon as the
* operation structure is either finished or passed it is no
* longer valid for use in any other function.
*
*
*
globus_xio_driver_handle_t
*
* A globus_xio_driver_handle_t represents an open handle to the driver
* stack for XIO. The driver obtains a driver_handle by calling
* globus_xio_operation_get_driver_handle().
* The driver_handle allows the user to do some
* complex things that will be described later.
*
*
*
* @subsection globus_xio_driver_typical Typical Sequence:
* Here is a typical sequence of events for a globus_xio transform
* driver. All operations are initiated either by the application calling
* a function in the Globus XIO API, or from a driver above the transform
* driver in the stack passing an operation to this driver.
*
*
*
Open
*
* XIO calls the globus_xio_driver_transform_open_t function of the
* driver, passing it the operation and, in the case of a passive
* open, the link from a server accept. The driver typically
* allocates a private data structure containing the state it wishes
* to associate with this handle, and passes this along with a
* callback function pointer to globus_xio_driver_pass_open().
* This allows the other drivers in the XIO stack to continue to
* process the operation.
*
* After the lower drivers in the stack have completed processing
* the open, they will call globus_xio_driver_finished_open(),
* which will in turn call the callback function which the
* driver passed as a parameter to globus_xio_driver_pass_open().
* The driver then does any post-open operation needed, and then
* finishes the operation by calling
* globus_xio_driver_finished_open(), passing the private state
* data as the driver_handle parameter. This state
* data will be passed to future operation implementations done
* with this handle.
*
*
Read/Write
*
XIO calls the driver's
* globus_xio_driver_read_t or globus_xio_driver_write_t function
* with an operation as a parameter and the state date from
* the globus_xio_driver_finished_open() call. The driver then
* transforms the data if necessary and then calls
* the globus_xio_driver_pass_read() or
* globus_xio_driver_pass_write()
* which passes the operation down the XIO driver stack. When
* the driver below it on the XIO stack calls
* globus_xio_driver_finished_read() or
* globus_xio_driver_finished_write(), the callback which was
* passed is invoked. In that callback, the driver should itself
* call globus_xio_driver_finished_read() or
* globus_xio_driver_finished_write() to indicate completion.
*
*
*
Close
*
XIO calls the close interface function, passing an
* operation and the private driver state. The driver will call
* globus_xio_driver_pass_close() passing it the operation.
* When the close callback is received the driver calls
* globus_xio_driver_finished_close() passing it the
* operation. At this point, the driver typically frees its
* private data, as the handle is no longer valid.
*
*
*
* @section globus_xio_driver_attributes Globus XIO Attributes
* Attributes provide a way to pass additional metadata to driver operations.
* Most Globus XIO API functions include an attribute parameter. Each driver
* implements its own set of attribute handling function. To implement
* attributes, a driver must provide functions of these types:
*
* - globus_xio_driver_attr_init_t
* - globus_xio_driver_attr_copy_t
* - globus_xio_driver_attr_cntl_t
* - globus_xio_driver_attr_destroy_t
*
* Pointers to these functions are associated with the driver by calling
* globus_xio_driver_set_attr
*
* @section globus_xio_advanced_driver_programming Advanced Driver Programming
* The typical driver implementation is describe above. However globus_xio
* allows driver authors to do more advanced things such as initiating
* operations on their own.
*
*
*
Read Ahead
*
Once a handle is open, a driver can create operation structures
* from it. A driver can then request I/O from the driver
* stack before it receives a call to its own I/O interface
* functions, implementing read-ahead functionality. This can be done
* as follows:
*
*
*
Obtain a driver handle from the open operation by calling
* globus_xio_operation_get_driver_handle()
*
Create an operation by calling globus_xio_driver_operation_create()
* and pass it the driver_handle from the previous step
*
call globus_xio_driver_pass_read() using this operation. When the
* read callback is received, the driver saves the returned data in
* its private data and then calls globus_xio_driver_finished_read() on the
* operation.
*
When XIO calls the driver's read interface function,
* the driver can immediately call globus_xio_driver_finished_read()
* function after updating the iovec structure with the data it had
* previously read.
*
*
*
*/
/*******************************************************************
* callbacks
******************************************************************/
/**
* @brief Open and Close Callback Signature
* @ingroup globus_xio_driver
* @details
* This is the function signature of callbacks for the
* globus_xio_pass_open() and globus_xio_pass_close() functions.
*
* @param op
* The operation structure associated with the open or the
* close requested operation. The driver should call the
* appropriate finished operation to clean up this structure.
* @param result
* The result of the requested data operation
* @param user_arg
* The user pointer that is threaded through to the callback.
*/
typedef void
(*globus_xio_driver_callback_t)(
globus_xio_operation_t op,
globus_result_t result,
void * user_arg);
/**
* Data Callback interface
* @ingroup globus_xio_driver
*
* This is the function signature of read and write operation
* callbacks.
*
* @param op
* The operation structure associated with the read or write
* operation request. The driver should call the appropriate
* finished operation when it receives this operation.
*
* @param result
* The result of the requested data operation
*
* @param nbytes
* the number of bytes read or written
*
* @param user_arg
* The user pointer that is threaded through to the callback.
*/
typedef void
(*globus_xio_driver_data_callback_t)(
globus_xio_operation_t op,
globus_result_t result,
globus_size_t nbytes,
void * user_arg);
typedef globus_result_t
(*globus_xio_driver_push_driver_t)(
globus_xio_driver_t driver,
globus_xio_stack_t stack);
globus_result_t
globus_xio_driver_attr_cntl(
globus_xio_operation_t op,
globus_xio_driver_t driver,
int cmd,
...);
globus_result_t
globus_xio_driver_data_descriptor_cntl(
globus_xio_operation_t op,
globus_xio_driver_t driver,
int cmd,
...);
/**
* @ingroup globus_xio_driver
* Touch driver specific information in a handle object.
*
* pass the driver to control a specific driver
* pass NULL for driver for XIO specific cntls
* pass GLOBUS_XIO_QUERY for driver to try each driver (below current)
* in order
*/
globus_result_t
globus_xio_driver_handle_cntl(
globus_xio_driver_handle_t handle,
globus_xio_driver_t driver,
int cmd,
...);
/**
* @ingroup globus_xio_driver
*/
typedef globus_result_t
(*globus_xio_driver_get_driver_t)(
globus_xio_driver_t * out_driver);
/**
* @ingroup globus_xio_driver
* Create a driver specific attribute.
*
* The driver should implement this function to create a driver
* specific attribute and return it via the out_attr parameter.
*
*/
typedef globus_result_t
(*globus_xio_driver_attr_init_t)(
void ** out_driver_attr);
/**
* @ingroup globus_xio_driver
* Copy a driver attr.
*
* When this function is called the driver will create a copy of the attr
* in parameter src and place it in the parameter dst.
*/
typedef globus_result_t
(*globus_xio_driver_attr_copy_t)(
void ** dst,
void * src);
/**
* @ingroup globus_xio_driver
* Destroy the driver attr.
*
* Clean up all resources associate with the attr.
*
*/
typedef globus_result_t
(*globus_xio_driver_attr_destroy_t)(
void * driver_attr);
/**
* @ingroup globus_xio_driver
* get or set information in an attr.
*
* The cmd parameter determines what functionality the user is requesting.
* The driver is responsible for providing documentation to the user on
* all the possible values that cmd can be.
*
* @param driver_attr
* The driver specific attr, created by
* globus_xio_driver_attr_init_t.
*
* @param cmd
* An integer representing what functionality the user is requesting.
*
* @param ap
* variable arguments. These are determined by the driver and the
* value of cmd.
*/
typedef globus_result_t
(*globus_xio_driver_attr_cntl_t)(
void * driver_attr,
int cmd,
va_list ap);
/**
* @ingroup globus_xio_driver
* Initialize a server object
*
* The driver developer should implement this function if their driver
* handles server operations (passive opens). In the TCP driver this
* function creates a TCP socket and calls listen() on it. Unlike all
* other XIO driver implementation functions, the globus_xio_server_create()
* function begins at the bottom (transport driver) of the stack, and
* the globus_xio_driver_pass_server_init() acts like a finished() operation.
*
* @param driver_attr
* A driver-specific attribute. This may be NULL.
* @param contact_info
* Contact information from the stack below this driver.
* This is NULL for the transport driver.
* @param op
* An op which must be passed to globus_xio_driver_pass_server_init()
* to pass the server contact information up the XIO driver stack.
*
* @return
* Returning GLOBUS_SUCCESS for this means that
* globus_xio_driver_pass_server_init returned success and
* the driver's server-specific data is initialized.
*/
typedef globus_result_t
(*globus_xio_driver_server_init_t)(
void * driver_attr,
const globus_xio_contact_t * contact_info,
globus_xio_operation_t op);
/**
* signify that the server has been created with this call. Must be called
* within the call to the driver's globus_xio_driver_server_init_t
* interface. This call is different than all other pass calls, as it operates
* from the bottom of the stack to the top. If it returns an error, the user
* should destroy their driver_server.
*
* @param op
* The operation passed to the globus_xio_driver_server_init_t
* function.
*
* @param contact_info
* The contact info for this driver and the stack below. If the driver
* has nothing to add, it should just pass the one it received on the
* interface.
*
* The memory for this contact_info is only needed for the life of the
* call, so it is acceptable for it to be declared on the stack and
* it is acceptable to 'steal' pointers from the received contact_info.
*
* @param driver_server
* The driver's server-specific state. Future calls to the
* server_accept, server_cntl, and server_destroy will be passed this
* value.
*/
globus_result_t
globus_xio_driver_pass_server_init(
globus_xio_operation_t op,
const globus_xio_contact_t * contact_info,
void * driver_server);
/**
* @ingroup globus_xio_driver
* destroy a server.
*
* When this function is called the driver should free up all resources
* associated with a server.
*
* @param driver_server
* The reference to the internal server that is being declared
* invalid with this function call.
*/
typedef globus_result_t
(*globus_xio_driver_server_destroy_t)(
void * driver_server);
/**
* @ingroup globus_xio_driver
* Accept a server connection
*
* The driver developer should implement this function if their driver
* handles server operations. Once the accept operation completes, the
* connection is established. The user still has an opportunity to
* open the link or destroy it. They can query the link for
* additional information on which to base the decision to open.
*
* @param driver_server
* The server object from which the link connection will be
* accepted.
*
* @param op
* The requested operation. When the driver is finished accepting
* the server connection it uses this structure to signal globus_xio
* that it has completed the operation.
*/
typedef globus_result_t
(*globus_xio_driver_server_accept_t)(
void * driver_server,
globus_xio_operation_t op);
globus_result_t
globus_xio_driver_pass_accept(
globus_xio_operation_t op,
globus_xio_driver_callback_t in_cb,
void * in_user_arg);
/**
* @ingroup globus_xio_driver
*/
typedef void
(*globus_xio_driver_cancel_callback_t)(
globus_xio_operation_t op,
void * user_arg,
globus_xio_error_type_t reason);
/**
* @ingroup globus_xio_driver
* Driver API finished accept
*
* This function should be called to signal globus_xio that it has
* completed the accept operation requested of it. It will free up
* resources associated with the accept_op and potentially cause xio
* to pop the signal up the driver stack.
*
* @param op
* The requested accept operation that has completed.
*
* @param driver_link
* This is the initialized driver link that is that will be passed to
* the open interface when this handle is opened.
*
* @param result
* Return status of the completed operation
*/
void
globus_xio_driver_finished_accept(
globus_xio_operation_t op,
void * driver_link,
globus_result_t result);
/**
* @ingroup globus_xio_driver
* Query a server for information.
*
* This function allows a user to request information from a driver
* specific server handle.
*
* @param driver_server
* the server handle.
*
* @param cmd
* An integer telling the driver what operation to preform on this
* server handle.
*
* @param ap
* variable args.
*/
typedef globus_result_t
(*globus_xio_driver_server_cntl_t)(
void * driver_server,
int cmd,
va_list ap);
/**
* @ingroup globus_xio_driver
*/
typedef globus_result_t
(*globus_xio_driver_link_cntl_t)(
void * driver_link,
int cmd,
va_list ap);
/**
* @ingroup globus_xio_driver
* destroy a link
*
* The driver should clean up all resources associated with the link
* when this function is called.
*
* @param driver_link
* The link to be destroyed.
*/
typedef globus_result_t
(*globus_xio_driver_link_destroy_t)(
void * driver_link);
/**********************************************************************
* Open
*********************************************************************/
/**
* @brief Open a handle
* @ingroup globus_xio_driver
* @details
* This is called when a user opens a handle.
*
* @param contact_info
* Contains information about the requested resource. Its members
* may all be null (especially when link is not null). XIO will
* destroy this contact info upon return from the interface function
*
* @param driver_link
* Comes from server accept. Used to link an accepted connection to
* an xio handle. XIO will destroy this object upon the return of
* this interface call.
*
* @param driver_attr
* A attribute describing how to open. This points to a piece of
* memory created by the globus_xio_driver_attr_init_t
* interface function.
*
* @param op
* The open operation. When the driver is finished opening
* the handle, it passes this to globus_xio_driver_finished_open()
* to return status up the driver stack to the application.
*
*/
typedef globus_result_t
(*globus_xio_driver_transform_open_t)(
const globus_xio_contact_t * contact_info,
void * driver_link,
void * driver_attr,
globus_xio_operation_t op);
/**
* @ingroup globus_xio_driver
* @copydoc globus_xio_driver_transform_open_t
*/
typedef globus_result_t
(*globus_xio_driver_transport_open_t)(
const globus_xio_contact_t * contact_info,
void * driver_link,
void * driver_attr,
globus_xio_operation_t op);
/**
* Driver API Open
* @ingroup globus_xio_driver
*
* This function will pass an open request down the driver stack.
* Upon completion of the open operation globus_xio will call the @a cb
* function, at which point the handle structure will be initialized
* and available for use.
*
* As soon as the function returns the handle is valid for creating
* other operations.
*
* @param op
* The operation from which the handle will be established. This
* parameter is used to determine what drivers are in the stack and
* other such information.
*
* @param contact_info
* The contact info describing the resource the driver below should
* open. This will normally be the same contact info that was
* passed in on the open interface.
*
* @param cb
* The function to be called when the open operation is complete.
*
* @param user_arg
* a user pointer that will be threaded through to the callback.
*/
globus_result_t
globus_xio_driver_pass_open(
globus_xio_operation_t op,
const globus_xio_contact_t * contact_info,
globus_xio_driver_callback_t cb,
void * user_arg);
/**
* Driver API finished open
* @ingroup globus_xio_driver
*
* This function should be called to signal globus_xio that it has
* completed the open operation requested of it. It will free up
* resources associated with the op and potentially cause xio
* to pop the signal up the driver stack.
*
* @param driver_handle
* The driver specific handle pointer that will be passed to
* future interface function calls.
*
* @param op
* The requested open operation that has completed.
*
* @param result
* Return status of the completed operation
*/
void
globus_xio_driver_finished_open(
void * driver_handle,
globus_xio_operation_t op,
globus_result_t result);
/**********************************************************************
* Context functions
*********************************************************************/
/**
* Driver API Create Operation
* @ingroup globus_xio_driver
*
* This function will create an operation from an initialized handle
* This operation can then be used for io operations related to the
* handle that created them.
*
* @param operation
* The operation to be created. When this function returns
* this structure will be populated and available for use
* for the driver.
*
* @param handle
* The initialized handle representing the user handle from
* which the operation will be created.
*
*/
globus_result_t
globus_xio_driver_operation_create(
globus_xio_operation_t * operation,
globus_xio_driver_handle_t handle);
/**
* @ingroup globus_xio_driver
*/
void
globus_xio_driver_operation_destroy(
globus_xio_operation_t operation);
/**
* @ingroup globus_xio_driver
*/
globus_result_t
globus_xio_driver_operation_cancel(
globus_xio_driver_handle_t handle,
globus_xio_operation_t operation);
/**
* Is Operation blocking.
* @ingroup globus_xio_driver
*
* If the operation is blocking the driver developer may be able to make
* certain optimizations. The function returns true if the given operation
* was created via a user call to a blocking function.
*/
globus_bool_t
globus_xio_driver_operation_is_blocking(
globus_xio_operation_t operation);
/**
* @ingroup globus_xio_driver
*
* this call *must* return an GLOBUS_XIO_ERROR_COMMAND error for unsupported
* command numbers. (use GlobusXIOErrorInvalidCommand(cmd))
*
* Drivers that have reason to support the commands listed at
* @ref globus_xio_handle_cmd_t should accept the xio generic cmd numbers
* and their driver specific command number. Do NOT implement those handle
* cntls unless you really are the definitive source.
*/
typedef globus_result_t
(*globus_xio_driver_handle_cntl_t)(
void * handle,
int cmd,
va_list ap);
globus_result_t
globus_xio_driver_merge_handle(
globus_xio_operation_t op,
globus_xio_driver_handle_t handle);
/**********************************************************************
* Close
*********************************************************************/
/**
* @brief Close a handle
* @ingroup globus_xio_driver
* @details
* This closes a handle. Driver implementations should pass the close to the
* other drivers in the stack by calling globus_xio_pass_close().
*
* In the close callback, the driver should clean up the data
* associated with driver_handle.
* @param driver_specific_handle
* The driver handle to be closed.
* @param driver_attr
* A driver specific attr which may be used to alter how a close
* is performed (e.g. caching drivers)
* @param op
* The open operation. When the driver is finished opening
* the handle, it passes this to globus_xio_driver_finished_close()
* to return status up the driver stack to the application.
*/
typedef globus_result_t
(*globus_xio_driver_close_t)(
void * driver_specific_handle,
void * driver_attr,
globus_xio_operation_t op);
/**
* @brief Pass the close operation down the driver stack
* @ingroup globus_xio_driver
* @details
* This function will pass a close request down the driver stack. Upon
* completion of the close operation globus_xio will call the function
* pointed to by the cb parameter.
*
* @param op
* The close operation.
* @param cb
* A pointer to the function to be called once all drivers lower
* in the stack have closed.
* @param callback_arg
* A pointer that will be passed to the callback.
*/
globus_result_t
globus_xio_driver_pass_close(
globus_xio_operation_t op,
globus_xio_driver_callback_t cb,
void * callback_arg);
/**
* Driver API finished_close
* @ingroup globus_xio_driver
*
* The driver calls this function after completing a close operation
* on a driver_handle. Once this function returns the driver_handle is
* no longer
* valid.
*
* @param op
* The close operation that has completed.
*
* @param result
* Return status of the completed operation
*/
void
globus_xio_driver_finished_close(
globus_xio_operation_t op,
globus_result_t result);
/**********************************************************************
* Read
*********************************************************************/
/**
* Read data from an open handle.
* @ingroup globus_xio_driver
*
* This function is called when the user requests to read data from
* a handle. The driver author shall implement all code needed to for
* there driver to complete a read operations.
*
* @param driver_specific_handle
* The driver handle from which data should be read.
*
* @param iovec
* An io vector pointing to the buffers to be read into.
*
* @param iovec_count
* The number if entries in the io vector.
*
* @param op
* The requested operation. When the driver is finished fulfilling
* the requested read operation it must use this structure to
* signal globus_xio that the operation is completed. This is done
* by calling globus_xio_driver_finished_operation().
*/
typedef globus_result_t
(*globus_xio_driver_read_t)(
void * driver_specific_handle,
const globus_xio_iovec_t * iovec,
int iovec_count,
globus_xio_operation_t op);
/**
* Driver read
* @ingroup globus_xio_driver
*
* This function passes a read operation down the driver stack. After
* this function is called the op structure is no longer valid. However
* when the driver stack finishes servicing the read request it will
* pass a new operation structure in the function pointed to by cb.
* Finish read can be called on the new operation received.
*
* @param op
* The operation structure representing this requested io
* operation.
*
* @param iovec
* A pointer to the array of iovecs.
*
* @param iovec_count
* The number of iovecs in the array.
*
* @param wait_for
* The minimum number of bytes to read before returning. if a driver
* has no specific requirement, he should use the user's request
* available via GlobusXIOOperationMinimumRead(op)
* @param cb
* The function to be called when the operation request is
* completed.
*
* @param user_arg
* A user pointer that will be threaded through to the callback.
*/
globus_result_t
globus_xio_driver_pass_read(
globus_xio_operation_t op,
globus_xio_iovec_t * iovec,
int iovec_count,
globus_size_t wait_for,
globus_xio_driver_data_callback_t cb,
void * user_arg);
/**
* Finished Read
* @ingroup globus_xio_driver
*
* This function is called to signal globus_xio that the requested
* read operation has been completed.
*
* @param op
* The operation structure representing the requested read
* operation.
*
* @param result
* Return status of the completed operation
*
* @param nread
* The number of bytes read
*/
void
globus_xio_driver_finished_read(
globus_xio_operation_t op,
globus_result_t result,
globus_size_t nread);
/**
* EOF state manipulation
* @ingroup globus_xio_driver
*
* This function is used by drivers that allow multiple outstanding reads at
* a time. It can only be called on behalf of a read operation (while in the
* read interface call or the pass_read callback).
*
* Typical use for this would be to hold a driver specific lock and call this
* when an internal EOF has been received. The read operation this is called
* on behalf of must be finished with an EOF error or the results are
* undefined.
*
* In general, you should not have an EOF flag in your driver. Use this call
* and globus_xio_driver_eof_received() instead. This is necessary to support
* XIO's automatic EOF resetting. If your driver absolutely can not be read
* after an EOF has been set, then you will need your own EOF flag.
*
* This call will typically only be used just before a finished_read() call.
*
* @param op
* The operation structure representing the requested read
* operation.
*/
void
globus_xio_driver_set_eof_received(
globus_xio_operation_t op);
/**
* EOF state checking
* @ingroup globus_xio_driver
*
* This function is used by drivers that allow multiple outstanding reads at
* a time. It can only be called on behalf of a read operation (while in the
* read interface call or the pass_read callback).
*
* Typical use for this would be to hold a driver specific lock (the same one
* used when calling globus_xio_driver_set_eof_received()) and call this to
* see if an EOF has been received. If so, the operation should immediately be
* finished with an EOF error (do not _return_ an EOF error).
*
* This call will typically only be used in the read interface call.
*
* @param op
* The operation structure representing the requested read
* operation.
*
* @return
* GLOBUS_TRUE if EOF received, GLOBUS_FALSE otherwise.
*/
globus_bool_t
globus_xio_driver_eof_received(
globus_xio_operation_t op);
/**********************************************************************
* Write
*********************************************************************/
/**
* Write data from an open handle.
* @ingroup globus_xio_driver
*
* This function is called when the user requests to write data to
* a handle. The driver author shall implement all code needed to for
* there driver to complete write operations.
*
* @param driver_specific_handle
* The driver handle to which data should be written.
*
* @param iovec
* An io vector pointing to the buffers to be written.
*
* @param iovec_count
* The number if entries in the io vector.
*
* @param op
* The requested operation. When the driver is finished fulfilling
* the requested read operation it must use this structure to
* signal globus_xio that the operation is completed. This is done
* by calling globus_xio_driver_finished_operation().
*/
typedef globus_result_t
(*globus_xio_driver_write_t)(
void * driver_specific_handle,
const globus_xio_iovec_t * iovec,
int iovec_count,
globus_xio_operation_t op);
/**
* Driver write
* @ingroup globus_xio_driver
*
* This function passes a write operation down the driver stack. After
* this function is called the op structure is no longer valid. However
* when the driver stack finishes servicing the write request it will
* pass a new operation structure in the function pointed to by cb.
* Finished write can be called on the new operation received.
*
* @param op
* The operation structure representing this requested io
* operation.
*
* @param iovec
* A pointer to the array of iovecs.
*
* @param iovec_count
* The number of iovecs in the array.
*
* @param wait_for
* The minimum number of bytes to write before returning. If a driver
* has no specific requirement, he should use the user's request
* available via GlobusXIOOperationMinimumWrite(op)
*
* @param cb
* The function to be called when the operation request is
* completed.
*
* @param user_arg
* A user pointer that will be threaded through to the callback.
*/
globus_result_t
globus_xio_driver_pass_write(
globus_xio_operation_t op,
globus_xio_iovec_t * iovec,
int iovec_count,
globus_size_t wait_for,
globus_xio_driver_data_callback_t cb,
void * user_arg);
/**
* Finished Write
* @ingroup globus_xio_driver
*
* This function is called to signal globus_xio that the requested
* write operation has been completed.
*
* @param op
* The operation structure representing the requested write
* operation.
*
* @param result
* Return status of the completed operation
*
* @param nwritten
* The number of bytes written
*/
void
globus_xio_driver_finished_write(
globus_xio_operation_t op,
globus_result_t result,
globus_size_t nwritten);
/**
* Finishes an operation and merge two op structures.
* (XXX not implemented yet)
* @ingroup globus_xio_driver
*
* This function will join to operations together and signal globus_xio
* that it has completed. This is an advanced function. Most drivers will
* not require its use. This function takes an operation that was created
* by this driver and passed on to drivers lower on the stack and an
* operation that came in on the interface function (that has seen the top
* half of the stack) and joins them together. The purpose of this function
* is to join data descriptors that were pre-staged and cached with those
* that have later come in at the users request. See the read ahead doc
* for more information.
*
* @param top_op
* The operation that has seen the top part of the driver stack.
*
* @param bottom_op
* The operation that has seen the bottom part of the driver stack.
*
* (result is always success in this case. if there is an error, use the
* other finish() call)
*/
globus_result_t
globus_xio_driver_merge_operation(
globus_xio_operation_t top_op,
globus_xio_operation_t bottom_op);
/**********************************************************************
* data descriptors
*********************************************************************/
/**
* @defgroup globus_xio_data_descriptors Data descriptors
* @ingroup globus_xio
* @brief Data descriptors
*
* globus_xio uses data descriptors to associate meta data with the
* data being written or the data read.
*
* Data descriptors flow into the drivers read and write interface
* functions by way of the operation structure. If the driver is
* interested in viewing the data descriptor it can request it from
* the operation structure via a call to
* globus_xio_driver_operation_get_data_descriptor() and it can view
* any driver specific data descriptor via a call to
* globus_xio_driver_data_descriptor_get_specific(). The driver
* can modify values in the data descriptor by setting values before
* passing the request down the stack. Several functions are available
* to modify the data descriptors. There is no need to "set()" the
* data descriptors back into the operation. The functions for manipulating
* the values in a DD affect the values xio has directly.
*
* Data descriptors flow back to the driver in the callbacks for
* the data operations. When calling finished operation on a data
* operation the driver must pass in a data descriptor. It should get
* this data descriptor from the io operation callback.
*
* Life Cycle:
*
* Passing in a data descriptor:
* A data descriptor is first created by the globus_xio user. The user
* can add driver specific data descriptors to it. Once the user has
* created and set the attributes on its data descriptor to their liking
* they pass it into a globus_xio data operation (either read or write).
* When the data descriptor is passed on globus_xio will make an internal
* copy of it. It does this by first coping the user the level
* data descriptor and then walking through the list of driver specific
* data descriptor contained in to and requesting the driver make
* a copy of the driver specific data descriptor. If ever a driver
* specific data descriptor is NULL globus_xio need not call into its
* drivers dd_copy function. If ever the user level data descriptor is
* NULL globus_xio need not deal with the data descriptor functionality at
* all.
*
* A data descriptor coming back up the stack
* Once an io operation reaches the transport driver (the bottom of the
* stack) it takes on a slightly different role. On the way in it
* is describing what is requested to be done with the data, on the way
* out it is describing what has actually been done. Once the transport
* driver performs the operation it should adjust the data descriptor
* to reflect what has actually happened (few drivers will need to worry
* about this). Each driver on the way up can adjust the data
* descriptor and its driver specific data descriptor. When XIO reaches
* the top of the stack it calls a user callback. When that callback
* returns all memory associated with the data descriptor is cleaned up.
* The interface function globus_xio_driver_data_descriptor_free() is
* used for this.
*/
globus_result_t
globus_xio_driver_init(
globus_xio_driver_t * driver,
const char * driver_name,
void * user_data);
/**
* @ingroup globus_xio_driver
*/
globus_result_t
globus_xio_driver_get_user_data(
globus_xio_driver_t in_driver,
void ** out_user_data);
globus_result_t
globus_xio_operation_attr_cntl(
globus_xio_operation_t op,
globus_xio_attr_cmd_t cmd,
...);
/**
* @ingroup globus_xio_driver
*/
globus_result_t
globus_xio_driver_destroy(
globus_xio_driver_t driver);
/**
* @ingroup globus_xio_driver
*/
globus_result_t
globus_xio_driver_set_transport(
globus_xio_driver_t driver,
globus_xio_driver_transport_open_t transport_open_func,
globus_xio_driver_close_t close_func,
globus_xio_driver_read_t read_func,
globus_xio_driver_write_t write_func,
globus_xio_driver_handle_cntl_t handle_cntl_func);
/**
* @ingroup globus_xio_driver
*/
globus_result_t
globus_xio_driver_set_transform(
globus_xio_driver_t driver,
globus_xio_driver_transform_open_t transform_open_func,
globus_xio_driver_close_t close_func,
globus_xio_driver_read_t read_func,
globus_xio_driver_write_t write_func,
globus_xio_driver_handle_cntl_t handle_cntl_func,
globus_xio_driver_push_driver_t push_driver_func);
/**
* @ingroup globus_xio_driver
*/
globus_result_t
globus_xio_driver_set_server(
globus_xio_driver_t driver,
globus_xio_driver_server_init_t server_init_func,
globus_xio_driver_server_accept_t server_accept_func,
globus_xio_driver_server_destroy_t server_destroy_func,
globus_xio_driver_server_cntl_t server_cntl_func,
globus_xio_driver_link_cntl_t link_cntl_func,
globus_xio_driver_link_destroy_t link_destroy_func);
globus_result_t
globus_xio_driver_set_server_pre_init(
globus_xio_driver_t driver,
globus_xio_driver_server_init_t server_pre_init_func);
/**
* @ingroup globus_xio_driver
*/
globus_result_t
globus_xio_driver_set_attr(
globus_xio_driver_t driver,
globus_xio_driver_attr_init_t attr_init_func,
globus_xio_driver_attr_copy_t attr_copy_func,
globus_xio_driver_attr_cntl_t attr_cntl_func,
globus_xio_driver_attr_destroy_t attr_destroy_func);
/*
* operation accessors
*/
void
globus_xio_operation_block_timeout(
globus_xio_operation_t op);
void
globus_xio_operation_unblock_timeout(
globus_xio_operation_t op);
void
globus_xio_operation_refresh_timeout(
globus_xio_operation_t op);
/** returns true if operation already canceled */
globus_bool_t
globus_xio_operation_enable_cancel(
globus_xio_operation_t op,
globus_xio_driver_cancel_callback_t cb,
void * user_arg);
void
globus_xio_operation_disable_cancel(
globus_xio_operation_t op);
globus_bool_t
globus_xio_operation_is_canceled(
globus_xio_operation_t op);
globus_size_t
globus_xio_operation_get_wait_for(
globus_xio_operation_t op);
void *
globus_xio_operation_get_driver_specific(
globus_xio_operation_t op);
globus_xio_driver_t
globus_xio_operation_get_user_driver(
globus_xio_operation_t op);
globus_xio_driver_t
globus_xio_operation_get_transport_user_driver(
globus_xio_operation_t op);
/* this returns the handle to the drivers below you */
globus_xio_driver_handle_t
globus_xio_operation_get_driver_handle(
globus_xio_operation_t op);
/* this returns the handle to your driver.
* (only useful for canceling operations in your possession)
* or getting user handle associated with the driver
*/
globus_xio_driver_handle_t
globus_xio_operation_get_driver_self_handle(
globus_xio_operation_t op);
void *
globus_xio_operation_get_data_descriptor(
globus_xio_operation_t op,
globus_bool_t force_create);
globus_result_t
globus_xio_operation_copy_stack(
globus_xio_operation_t op,
globus_xio_stack_t * stack);
/* STRING PARSING STUFF */
/**
* @ingroup globus_xio_driver
*/
typedef globus_result_t
(*globus_xio_string_cntl_parse_func_t)(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func);
/**
* @ingroup globus_xio_driver
*/
typedef struct globus_xio_string_cntl_table_s
{
const char * key;
int cmd;
globus_xio_string_cntl_parse_func_t parse_func;
} globus_xio_string_cntl_table_t;
/**
*
* The set of interface functions that the driver author must implement
* to create a driver and the functions to assist in the creation.
*
* Driver attribute functions
*
* If the driver wishes to provide driver specific attributes to the
* user it must implement the following functions:
*
* globus_xio_driver_attr_init_t
* globus_xio_driver_attr_copy_t
* globus_xio_driver_attr_cntl_t
* globus_xio_driver_attr_destroy_t
*/
/**
* @defgroup string_globus_xio_driver_programming Driver Programming: String options
* @ingroup globus_xio_driver
* @brief Driver Programming: String options
*
* A driver can choose to expose parameters as in a string form. Providing
* this feature makes dynamically setting driver specific options much easier.
* a user can then load the driver by name and set specific options by name
* all at runtime with no object module references. For example, a TCP driver
* can be loaded with the string: tcp, and the options can be set with:
*
* port=50668;keepalive=yes;nodelay=N
*
* this would set the port to 50668, keepalive to true and nodelay to false.
* The particular string definition is defined by the tcp driver by properly
* creating a globus_i_xio_attr_parse_table_t array. Each element of the
* array is 1 options. There are 3 members of each array entry: key, cmd, and
* parse function. The key is a string that defines what option is to be set.
* In the above example string "port" would be 1 key. cmd tells the driver what
* cntl is associated with the key. In other words, once the string is parsed out
* what driver specific control must be called to set the requested option. For
* more information on controls see @ref globus_xio_attr_cntl. The final value
* in the array entry is the parsing function. The parsing function takes the
* value of the key=value portion of the string and parses it into data types.
* once parsed globus_xio_attr_cntl is called and thus the option is set. There are
* many available parsing functions but the developer is free to right their own
* if the provided ones are not sufficient. Sample parsing functions follow:
*
* - @ref globus_xio_string_cntl_bool
* - @ref globus_xio_string_cntl_float
* - @ref globus_xio_string_cntl_int
* - @ref globus_xio_string_cntl_string
* - @ref globus_xio_string_cntl_int_int
*/
/**
* Set the string table for attr cntl
* @ingroup string_globus_xio_driver_programming
*/
globus_result_t
globus_xio_driver_string_cntl_set_table(
globus_xio_driver_t driver,
globus_xio_string_cntl_table_t * table);
/**
* Set the string table for handle cntl
* @ingroup string_globus_xio_driver_programming
*/
globus_result_t
globus_xio_driver_handle_string_cntl_set_table(
globus_xio_driver_t driver,
globus_xio_string_cntl_table_t * table);
/**
* @ingroup string_globus_xio_driver_programming
*
* New type functions call this one
*/
globus_result_t
globus_xio_string_cntl_bouncer(
globus_xio_driver_attr_cntl_t cntl_func,
void * attr,
int cmd,
...);
/* list all of the built in parsing functions */
/**
* @ingroup string_globus_xio_driver_programming
*
* String option parsing function.
*/
globus_result_t
globus_xio_string_cntl_bool(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func);
/**
* @ingroup string_globus_xio_driver_programming
*
* String option parsing function.
*/
globus_result_t
globus_xio_string_cntl_float(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func);
/**
* @ingroup string_globus_xio_driver_programming
*
* String option parsing function.
*/
globus_result_t
globus_xio_string_cntl_int(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func);
/**
* @ingroup string_globus_xio_driver_programming
*
* String option parsing function.
*/
globus_result_t
globus_xio_string_cntl_string(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func);
/**
* @ingroup string_globus_xio_driver_programming
*
* String option parsing function.
*/
globus_result_t
globus_xio_string_cntl_int_int(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func);
globus_result_t
globus_xio_string_cntl_formated_off(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func);
globus_result_t
globus_xio_string_cntl_formated_int(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func);
globus_result_t
globus_xio_string_cntl_string_list(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func);
#ifdef __cplusplus
}
#endif
#endif /* GLOBUS_XIO_DRIVER_H */
globus_xio-6.6/PaxHeaders.22691/globus_xio.h 0000644 0000000 0000000 00000000132 14243161125 017061 x ustar 00 0000000 0000000 30 mtime=1653400149.721966443
30 atime=1653401470.564750367
30 ctime=1653403998.727961733
globus_xio-6.6/globus_xio.h 0000664 0001750 0001750 00000104323 14243161125 017224 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if !defined(GLOBUS_XIO_H)
#define GLOBUS_XIO_H
#include "globus_common.h"
#include "globus_xio_types.h"
#include "globus_xio_util.h"
#include "globus_xio_load.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef GLOBUS_GLOBAL_DOCUMENT_SET
/**
* @mainpage Globus XIO
* @copydoc globus_xio
*/
#endif
/**
* @defgroup globus_xio Globus XIO
* @brief eXtensible Input Output library
*
* - @ref GLOBUS_XIO_API
* - @ref GLOBUS_XIO_API_ASSIST
* - @ref globus_xio_driver
*/
/**
* @defgroup GLOBUS_XIO_API Globus XIO API
* @ingroup globus_xio
* @brief Globus XIO API
*/
/**
* @defgroup GLOBUS_XIO_API_ASSIST XIO Examples
* @ingroup globus_xio
* @brief XIO Examples
*
* Help understanding the globus_xio api.
*/
/**
* \addtogroup GLOBUS_XIO_API_ASSIST
*
* \section globus_xio_stack_construction Stack Construction
* The driver stack that is used for a given XIO handle is constructed
* using a globus_xio_stack_t. Each driver is loaded by name
* and pushed onto a stack.
*
* Stack setup example:
* \code
// First load the drivers
globus_xio_driver_load("tcp", &tcp_driver);
globus_xio_driver_load("gsi", &gsi_driver);
//build the stack
globus_xio_stack_init(&stack);
globus_xio_stack_push_driver(stack, tcp_driver, NULL);
globus_xio_stack_push_driver(stack, gsi_driver, NULL);
\endcode
*/
/**
* \addtogroup GLOBUS_XIO_API_ASSIST
*
* \section globus_xio_servers Servers
* A server data structure provides functionality for passive opens.
* A server is initialized and bound to a protocol stack and set
* of attributes with the function globus_xio_server_create(). Once
* a server is created many "connections" can be accepted. Each connection
* will result in an initialized handle which can later be opened.
*
* \code
globus_xio_server_t server;
globus_xio_attr_t attr;
globus_xio_attr_init(&attr);
globus_xio_server_create(&server_handle, attr, stack);
globus_xio_server_accept(&handle, server);
\endcode
*/
/**
* \addtogroup GLOBUS_XIO_API_ASSIST
*
* \section globus_xio_handle_construction Handle Construction
* There are two ways to create a handle. The first is for use as a
* client (one that is doing an active open). The function:
* globus_xio_handle_create() is used to create such a handle and bind
* that handle to a protocol stack.
*
* \code
globus_xio_handle_create(&handle, stack);
\endcode
*
* The second means of creating a handle is for use as a server (one
* that is doing a passive open). This is created by accepting a
* connection on a server_handle with the function globus_xio_server_accept()
* or globus_xio_server_register_accept().
*
* Mutable attrs can be altered
* via a call to globus_xio_handle_cntl() described later.
*
* \code
globus_xio_server_accept(&xio_handle, server_handle);
\endcode
*
* once a handle is initialized the user can call globus_xio_open()
* to begin the open process.
*/
/**
* @addtogroup GLOBUS_XIO_API_ASSIST
*
* \section globus_xio_timeouts Timeouts
* A user can set a timeout value for any I/O operation. Each I/O
* operation (open close read write) can have its own timeout value.
* If no timeout is set the operation will be allowed to infinitely
* block.
*
* When time expires the outstanding operation is canceled. If the
* timeout callback for the given operation is not NULL it is called first to
* notify the user that the operation timed out and give the user a chance to
* ignore that timeout. If canceled, the user will get the callback they
* registered for the operation as well, but it will come with an error
* indicating that it has been canceled.
*
* It is possible that part of an I/O operation will complete before
* the timeout expires. In this case the operation can still be
* canceled. The user will receive there IO callback with and
* error set and the length value appropriately set to indicate how
* much of the operation completed.
*
* Timeouts are registered by using the following handle_cntl values:
*
* - GLOBUS_XIO_ATTR_SET_TIMEOUT_ALL
* - GLOBUS_XIO_ATTR_SET_TIMEOUT_OPEN
* - GLOBUS_XIO_ATTR_SET_TIMEOUT_CLOSE
* - GLOBUS_XIO_ATTR_SET_TIMEOUT_READ
* - GLOBUS_XIO_ATTR_SET_TIMEOUT_WRITE
* - GLOBUS_XIO_ATTR_SET_TIMEOUT_ACCEPT
*
* Each of these cntls expect three parameters:
*
* - globus_xio_timeout_callback_t callback_function
* - globus_reltime_t * delay_time
* - void * callback_arg
*/
/**
* @addtogroup GLOBUS_XIO_API_ASSIST
*
* \section data_descriptor Data Descriptor
* The data descriptor ADT gives the user a means of attaching/extracting
* meta data to a read or write operation.\n
* Things like offset, out of band message, and other driver specific
* meta data are contained in the data descriptor.\n
* Data descriptors are passed to globus_xio in globus_xio_read() and
* globus_xio_write(). Within the globus_xio framework
* it is acceptable to pass NULL instead of a valid data_descriptor,
*
* Example:
* \code
globus_xio_data_descriptor_init(&desc);
globus_xio_data_descriptor_cntl(desc,
tcp_driver,
GLOBUS_XIO_TCP_SET_SEND_FLAGS,
GLOBUS_XIO_TCP_SEND_OOB);
\endcode
*/
/*************************************************************************
* define types
************************************************************************/
/**
* \addtogroup GLOBUS_XIO_API_ASSIST
*
* \section user_attributes User Attributes
* Globus XIO uses a single attribute object for all of its functions.
* Attributes give the user an extensible mechanism to alter default
* values which control parameters in an operation.
*
* In most of the Globus XIO user API functions a user passes an
* attribute as a parameter. In many cases the user may ignore the
* attribute parameter and just pass in NULL. However at times the user
* will wish to tweak the operation. The attribute structure is used for
* this tweaking.
*
* There are only three attribute functions. @ref globus_xio_attr_init
* @ref globus_xio_attr_cntl and @ref globus_xio_attr_destroy. The
* init and destroy functions are very simple and require little explanation.
* Before an attribute can be used it must be initialized, and to clean up all
* memory associated with it the user must call destroy on it.
*
* The function @ref globus_xio_attr_cntl manipulates values in the
* attribute. For more info on it see @ref globus_xio_attr_cntl.
*/
/**
* \ingroup GLOBUS_XIO_API
* Initialize a Globus XIO attribute.
*
* @param attr
* upon return from this function this out parameter will be
* initialized. Once the user is finished with the attribute
* they should make sure they destroy it in order to free
* resources associated with it.
*/
globus_result_t
globus_xio_attr_init(
globus_xio_attr_t * attr);
/**
* @ingroup GLOBUS_XIO_API
* Manipulate the values associated in the attr.
*
* This function provides a means to access the attr structure. What
* exactly this function does is determined by the value in the parameter
* cmd and the value of the parameter driver. When the driver parameter
* is NULL it indicates that this function applies to general Globus XIO
* values. If it is not NULL it indicates that the function will effect
* driver specific values. Each driver is responsible for defining its own
* enumeration of values for cmd and the var args associated with that
* command.
*
* @param attr
* the attribute structure to be manipulated.
*
* @param driver
* This parameter indicates which driver the user would like
* to perform the requested operation. If this parameter is
* NULL this request will be scoped to general attribute functions.
*
* @param cmd
* an enum that determines what specific operation the user is
* requesting. Each driver will determine the value for this
* enumeration.
*/
globus_result_t
globus_xio_attr_cntl(
globus_xio_attr_t attr,
globus_xio_driver_t driver,
int cmd,
...);
/**
* @ingroup GLOBUS_XIO_API
*
* Copy an attribute structure.
*/
globus_result_t
globus_xio_attr_copy(
globus_xio_attr_t * dst,
globus_xio_attr_t src);
/**
* @ingroup GLOBUS_XIO_API
* Clean up resources associated with an attribute.
*
* @param attr
* Upon completion of this function all resources associated
* with this structure will returned to the system and the attr
* will no longer be valid.
*/
globus_result_t
globus_xio_attr_destroy(
globus_xio_attr_t attr);
/*************************************************************************
* Stack functions
* ---------------
************************************************************************/
/**
* @ingroup GLOBUS_XIO_API
* Initialize a stack object
*/
globus_result_t
globus_xio_stack_init(
globus_xio_stack_t * stack,
globus_xio_attr_t stack_attr);
/**
* @ingroup GLOBUS_XIO_API
* Push a driver onto a stack.
*
* No attrs are associated with a driver. The stack represents the
* ordered lists of transform drivers and 1 transport driver. The
* transport driver must be pushed on first.
*/
globus_result_t
globus_xio_stack_push_driver(
globus_xio_stack_t stack,
globus_xio_driver_t driver);
/**
* @ingroup GLOBUS_XIO_API
* Copy a stack object
*/
globus_result_t
globus_xio_stack_copy(
globus_xio_stack_t * dst,
globus_xio_stack_t src);
/**
* @ingroup GLOBUS_XIO_API
* Destroy a stack object.
*/
globus_result_t
globus_xio_stack_destroy(
globus_xio_stack_t stack);
/*-------------------------------------------------------------------------
* server
*-----------------------------------------------------------------------*/
/**
* @ingroup GLOBUS_XIO_API
* Callback signature for accept.
*
* When a registered accept operation completes the users function of
* this signature is called.
*
* @param server
* The server object on which the accept was registered.
*
* @param handle
* The newly created handle that was created by the accept
* operation.
*
* @param result
* A result code indicating the success of the accept operation.
* GLOBUS_SUCCESS indicates a successful accept.
*
* @param user_arg
* A user argument that is threaded from the registration to the
* callback.
*/
typedef void
(*globus_xio_accept_callback_t)(
globus_xio_server_t server,
globus_xio_handle_t handle,
globus_result_t result,
void * user_arg);
/**
* @ingroup GLOBUS_XIO_API
* Server callback signature.
*
* This is the generic server callback signature. It is currently only
* used for the register close operation.
*/
typedef void
(*globus_xio_server_callback_t)(
globus_xio_server_t server,
void * user_arg);
/**
* @ingroup GLOBUS_XIO_API
* Create a server object.
*
* This function allows the user to create a server object which can then
* be used to accept connections.
*
* @param server
* An out parameter. Once the function successfully returns this
* will point to a valid server object.
*
* @param server_attr
* an attribute structure used to alter the default server
* initialization. This will mostly be used in a driver specific manner.
* can be NULL.
*
* @param stack
*/
globus_result_t
globus_xio_server_create(
globus_xio_server_t * server,
globus_xio_attr_t server_attr,
globus_xio_stack_t stack);
/**
* @ingroup GLOBUS_XIO_API
* get contact string
*
* This function allows the user to get the contact string for a server.
* this string could be used as the contact string for the client side.
*
* @param server
* An initialized server handle created with globus_xio_server_create()
*
* @param contact_string
* an out variable. Will point to a newly allocated string on success.
* must be freed by the caller.
*/
globus_result_t
globus_xio_server_get_contact_string(
globus_xio_server_t server,
char ** contact_string);
/**
* @ingroup GLOBUS_XIO_API
* post a close on a server object
*
* This function registers a close operation on a server. When the user
* function pointed to by parameter cb is called the server object is closed.
*/
globus_result_t
globus_xio_server_register_close(
globus_xio_server_t server,
globus_xio_server_callback_t cb,
void * user_arg);
/**
* @ingroup GLOBUS_XIO_API
* A blocking server close
*/
globus_result_t
globus_xio_server_close(
globus_xio_server_t server);
/**
* @ingroup GLOBUS_XIO_API
* Touch driver specific information in a server object.
*
* This function allows the user to communicate directly with a driver
* in association with a server object. The driver defines what operations
* can be preformed.
*/
globus_result_t
globus_xio_server_cntl(
globus_xio_server_t server,
globus_xio_driver_t driver,
int cmd,
...);
/**
* @ingroup GLOBUS_XIO_API
* Accept a connection
*
* This function will accept a connection on the given server object
* and the parameter out_handle will be valid if the function returns
* successfully.
*/
globus_result_t
globus_xio_server_accept(
globus_xio_handle_t * out_handle,
globus_xio_server_t server);
/**
* @ingroup GLOBUS_XIO_API
* Asynchronous accept.
*
* This function posts an nonblocking accept. Once the operation has
* completed the user function pointed to by the parameter cb is called.
*/
globus_result_t
globus_xio_server_register_accept(
globus_xio_server_t server,
globus_xio_accept_callback_t cb,
void * user_arg);
/**
* @ingroup GLOBUS_XIO_API
* Initialize a handle for client opens
*
* This function will initialize a handle for active opens (client side
* connections).
*
*/
globus_result_t
globus_xio_handle_create(
globus_xio_handle_t * handle,
globus_xio_stack_t stack);
/******************************************************************
* handle construction
*****************************************************************/
/******************************************************************
* setting timeout values
*****************************************************************/
/**
* @ingroup GLOBUS_XIO_API
* The timeout callback function signature.
*
* @param handle
* The handle the handle on which the timeout operation was
* requested.
*
* @param type
* The type of operation that timed out:
* GLOBUS_XIO_OPERATION_OPEN
* GLOBUS_XIO_OPERATION_CLOSE
* GLOBUS_XIO_OPERATION_READ
* GLOBUS_XIO_OPERATION_WRITE
*
* @param user_arg
* A user arg threaded through to the callback.
*/
typedef globus_bool_t
(*globus_xio_timeout_callback_t)(
globus_xio_handle_t handle,
globus_xio_operation_type_t type,
void * user_arg);
typedef globus_bool_t
(*globus_xio_timeout_server_callback_t)(
globus_xio_server_t server,
globus_xio_operation_type_t type);
/******************************************************************
* data descriptor
*****************************************************************/
/**
* Initialize a data descriptor
* @ingroup GLOBUS_XIO_API
*
* @param data_desc
* An out parameter. The data descriptor to be initialized.
*
* @param handle
* The handle this data descriptor will be used with. This
* parameter is require in order to optimize the code
* handling the data descriptors use.
*/
globus_result_t
globus_xio_data_descriptor_init(
globus_xio_data_descriptor_t * data_desc,
globus_xio_handle_t handle);
/**
* @ingroup GLOBUS_XIO_API
* clean up a data descriptor.
*/
globus_result_t
globus_xio_data_descriptor_destroy(
globus_xio_data_descriptor_t data_desc);
/**
* Touch driver specific data in data descriptors
* @ingroup GLOBUS_XIO_API
*
* This function allows the user to communicate directly with a driver
* in association with a data descriptors. The driver defines what operations
* can be preformed.
*/
globus_result_t
globus_xio_data_descriptor_cntl(
globus_xio_data_descriptor_t data_desc,
globus_xio_driver_t driver,
int cmd,
...);
/*********************************************************************
* callbacks
********************************************************************/
/**
* globus_xio_callback_t
* @ingroup GLOBUS_XIO_API
*
* This callback is used for the open and close asynchronous
* operations.
*/
typedef void (*globus_xio_callback_t)(
globus_xio_handle_t handle,
globus_result_t result,
void * user_arg);
/**
* globus_xio_data_callback_t
* @ingroup GLOBUS_XIO_API
*
* This callback is used for asynchronous operations that send or receive
* data.
*
* On EOF, result_t will be of type GLOBUS_XIO_ERROR_EOF
*/
typedef void (*globus_xio_data_callback_t)(
globus_xio_handle_t handle,
globus_result_t result,
globus_byte_t * buffer,
globus_size_t len,
globus_size_t nbytes,
globus_xio_data_descriptor_t data_desc,
void * user_arg);
/**
* globus_xio_iovec_callback_t
* @ingroup GLOBUS_XIO_API
*
* This callback is used for asynchronous operations that send or receive
* data with an iovec structure.
*
* On EOF, result_t will be of type GLOBUS_XIO_ERROR_EOF
*/
typedef void (*globus_xio_iovec_callback_t)(
globus_xio_handle_t handle,
globus_result_t result,
globus_xio_iovec_t * iovec,
int count,
globus_size_t nbytes,
globus_xio_data_descriptor_t data_desc,
void * user_arg);
/**
* @ingroup GLOBUS_XIO_API
* Touch driver specific information in a handle object.
*
* This function allows the user to communicate directly with a driver
* in association with a handle object. The driver defines what operations
* can be preformed.
*
* pass the driver to control a specific driver
* pass NULL for driver for XIO specific cntls
* pass GLOBUS_XIO_QUERY for driver to try each driver in order until success
*/
globus_result_t
globus_xio_handle_cntl(
globus_xio_handle_t handle,
globus_xio_driver_t driver,
int cmd,
...);
/**
* Open a handle
* @ingroup GLOBUS_XIO_API
*
* Creates an open handle based on the state contained in the given
* stack.
*
* No operation can be preformed on a handle until it is initialized
* and then opened. If
* an already open handle used the information contained in that handle
* will be destroyed.
*
* @param handle
* The handle created with @ref globus_xio_handle_create() or
* @ref globus_xio_server_register_accept() that is to be opened.
*
* @param attr
* how to open attribute. can be NULL
*
* @param cb
* The function to be called when the open operation completes.
*
* @param user_arg
* A user pointer that will be threaded through to the callback.
*
* @param contact_string
* An url describing the resource. NULL is allowed.
* Drivers interpret the various parts
* of this url as described in their documentation. An alternative
* form is also supported: if contact_string does not specify a scheme
* (e.g. http://) and it contains a ':', it will be parsed as a host:port
* pair. if it does not contain a ':', it will be parsed as the path
*
* the following are examples of valid formats:
*
*
* Except for use as the above delimiters, the following special characters
* MUST be encoded with the \%HH format where H == hex char.
*
*
* "/" and "@" in location except subject
* "<" and ">" in location
* ":" everywhere except ipv6 address and subject
* "%" everywhere (can be encoded with \%HH or \%%)
*
*/
globus_result_t
globus_xio_register_open(
globus_xio_handle_t handle,
const char * contact_string,
globus_xio_attr_t attr,
globus_xio_callback_t cb,
void * user_arg);
/**
* Blocking open
* @ingroup GLOBUS_XIO_API
*/
globus_result_t
globus_xio_open(
globus_xio_handle_t handle,
const char * contact_string,
globus_xio_attr_t attr);
/**
* Read data from a handle
* @ingroup GLOBUS_XIO_API
*/
globus_result_t
globus_xio_register_read(
globus_xio_handle_t handle,
globus_byte_t * buffer,
globus_size_t buffer_length,
globus_size_t waitforbytes,
globus_xio_data_descriptor_t data_desc,
globus_xio_data_callback_t cb,
void * user_arg);
/**
* Read data from a handle
* @ingroup GLOBUS_XIO_API
*/
globus_result_t
globus_xio_read(
globus_xio_handle_t handle,
globus_byte_t * buffer,
globus_size_t buffer_length,
globus_size_t waitforbytes,
globus_size_t * nbytes,
globus_xio_data_descriptor_t data_desc);
/**
* Read data from a handle into a globus_xio_iovec_t (struct iovec)
* @ingroup GLOBUS_XIO_API
*/
globus_result_t
globus_xio_register_readv(
globus_xio_handle_t handle,
globus_xio_iovec_t * iovec,
int iovec_count,
globus_size_t waitforbytes,
globus_xio_data_descriptor_t data_desc,
globus_xio_iovec_callback_t cb,
void * user_arg);
/**
* Read data from a handle into a globus_xio_iovec_t (struct iovec)
* @ingroup GLOBUS_XIO_API
*/
globus_result_t
globus_xio_readv(
globus_xio_handle_t handle,
globus_xio_iovec_t * iovec,
int iovec_count,
globus_size_t waitforbytes,
globus_size_t * nbytes,
globus_xio_data_descriptor_t data_desc);
/**
* Write data to a handle
* @ingroup GLOBUS_XIO_API
*/
globus_result_t
globus_xio_register_write(
globus_xio_handle_t handle,
globus_byte_t * buffer,
globus_size_t buffer_length,
globus_size_t waitforbytes,
globus_xio_data_descriptor_t data_desc,
globus_xio_data_callback_t cb,
void * user_arg);
/**
* Write data to a handle
* @ingroup GLOBUS_XIO_API
*/
globus_result_t
globus_xio_write(
globus_xio_handle_t handle,
globus_byte_t * buffer,
globus_size_t buffer_length,
globus_size_t waitforbytes,
globus_size_t * nbytes,
globus_xio_data_descriptor_t data_desc);
/**
* Write data to a handle from a globus_xio_iovec_t (struct iovec)
* @ingroup GLOBUS_XIO_API
*/
globus_result_t
globus_xio_register_writev(
globus_xio_handle_t handle,
globus_xio_iovec_t * iovec,
int iovec_count,
globus_size_t waitforbytes,
globus_xio_data_descriptor_t data_desc,
globus_xio_iovec_callback_t cb,
void * user_arg);
/**
* Write data to a handle from a globus_xio_iovec_t (struct iovec)
* @ingroup GLOBUS_XIO_API
*/
globus_result_t
globus_xio_writev(
globus_xio_handle_t handle,
globus_xio_iovec_t * iovec,
int iovec_count,
globus_size_t waitforbytes,
globus_size_t * nbytes,
globus_xio_data_descriptor_t data_desc);
/**
* Cancel outstanding operations
*/
globus_result_t
globus_xio_handle_cancel_operations(
globus_xio_handle_t handle,
int mask);
globus_result_t
globus_xio_server_cancel_accept(
globus_xio_server_t server);
/**
* Close a handle
* @ingroup GLOBUS_XIO_API
*
* This functions servers as a destroy for the handle. As soon as the
* operations completes (the callback is called). The handle is
* destroyed.
*
* @param handle
* the handle to be closed.
*
* @param attr
* how to close attribute
*
* @param cb
* The function to be called when the close operation completes.
*
* @param user_arg
* A user pointer that will be threaded through to the callback.
*/
globus_result_t
globus_xio_register_close(
globus_xio_handle_t handle,
globus_xio_attr_t attr,
globus_xio_callback_t cb,
void * user_arg);
/**
* Blocking close
* @ingroup GLOBUS_XIO_API
*/
globus_result_t
globus_xio_close(
globus_xio_handle_t handle,
globus_xio_attr_t attr);
/*
* signal stuff
* TODO:
* Signals are not implemented in the first release.
* =================================================
*
* Signals in Globus XIO give the user a means of requesting
* notification when given things in the system change.
*
* For example:
* It may be useful for the user of globus_xio to know when/if the
* optimal post buffer size changes. The optimal post buffer size is
* a value that tells the user the best possible length of a buffer to
* post for an I/O operation. This value is mutable and can be changed
* by events internal to globus_xio of which the user is unaware.
* The signal API allows the user to register for notification of when
* this value changes.
*
* Globus XIO enumerates the signal types for which the user can register.
* One of these types is GLOBUS_XIO_DRIVER_SPECIFIC. This type allows
* the user to catch driver specific signals. A driver specific signal
* example could be when the TCP window size changes. Only a TCP driver
* can be aware of this information so only it can send the signal.
* Further a user only knows to listen for that signal if it knows that
* tcp is in its driver stack.
*
* Once a signal is delivered to the globus_xio user the handle can be
* queried for specific information regarding that signal.
* Event Types.
* @ingroup GLOBUS_XIO_API
*
* An enumeration of the signal types of which globus_xio is aware.
enum globus_xio_signal_type_t
{
GLOBUS_XIO_SIGNAL_BUFFER_POST_SIZE,
GLOBUS_XIO_SIGNAL_OPTIMAL_BUFFER_SIZE,
GLOBUS_XIO_SIGNAL_DRIVER_SPECIFIC,
};
*
* Signal Callback
* @ingroup GLOBUS_XIO_API
*
* The callback signature for signal events.
*
* @param handle
* The handle associated with the event.
*
* @param signal_type
* The type of signal that occurred.
*
* @param driver
* The driver that caused this event. If it is not a driver
* specific signal than this will be NULL.
typedef void
(*globus_xio_signal_callback_t)(
globus_xio_handle_t handle,
globus_xio_signal_type_t signal_type,
globus_xio_driver_t driver);
*
* Register a signal listener.
* @ingroup GLOBUS_XIO_API
*
* Request notification when event change in the system relating
* to a given handle.
*
* @param handle
* The handle on which the user would like to receive
* notifications.
*
* @param signal_mask
* A mask of the signals to be observed.
*
* @param driver
* The driver to which the signal mask applies. If this is for a
* non driver specific event this will be null. This function
* must be called once for every driver of interest.
*
* @param callback
* The function to be called when the given events occur.
*
* @param user_arg
* A user pointed threaded through to the callback.
globus_result_t
globus_xio_handle_register_signal_handler(
globus_xio_handle_t handle,
int signal_mask,
globus_xio_driver_t driver,
globus_xio_signal_callback_t callback,
void * user_arg);
* Register a signal listener.
* @ingroup GLOBUS_XIO_API
*
* Request notification when event change in the system relating
* to a given factory.
*
* @param factory
* The factory on which the user would like to receive
* notifications of events.
*
* @param signal_mask
* A mask of the signals to be observed.
*
* @param driver
* The driver to which the signal mask applies. If this is for a
* non driver specific event this will be null. This function
* must be called once for every driver of interest.
*
* @param callback
* The function to be called when the given events occur.
*
* @param user_arg
* A user pointed threaded through to the callback.
globus_result_t
globus_xio_server_register_signal_handler(
globus_xio_server_t factory,
int signal_mask,
globus_xio_driver_t driver,
globus_xio_callback_t callback,
void * user_arg);
*/
globus_xio_driver_list_ent_t *
globus_xio_driver_list_find_driver(
globus_list_t * driver_list,
const char * driver_name);
void
globus_xio_driver_list_destroy(
globus_list_t * driver_list,
globus_bool_t unload);
globus_result_t
globus_xio_driver_list_to_stack_attr(
globus_list_t * driver_list,
globus_xio_stack_t stack,
globus_xio_attr_t attr);
globus_result_t
globus_xio_driver_list_from_string(
char * driver_string,
globus_list_t ** driver_list,
globus_hashtable_t * safe_table);
globus_result_t
globus_xio_driver_safe_table_from_string(
char * driver_string,
globus_hashtable_t * safe_table);
globus_result_t
globus_xio_driver_list_create_ent(
const char * driver_desc,
globus_xio_driver_t driver_in,
globus_bool_t load,
globus_xio_driver_list_ent_t ** ent_out);
extern globus_module_descriptor_t globus_i_xio_module;
#define GLOBUS_XIO_MODULE &globus_i_xio_module
#define _XIOSL(s) globus_common_i18n_get_string( \
GLOBUS_XIO_MODULE, \
s)
/**
* @ingroup GLOBUS_XIO_API
* Initializes a handle based on the scheme given.
*
* @param out_h
* An uninitialized handle that will be initialized in the function
* to correspond to the scheme given. This handle should be used
* for any I/O operations.
*
* @param scheme
* A string containing the protocol which the handle should be
* initialized to. The string can either be a protocol by itself,
* for example, "http", or a complete scheme such as
* "http://www.example.com".
*
* @param attr
* Attribute to be used for setting parameter string. It is
* initialized by the function. Can be NULL if attributes
* are not being used.
*
* @param param_string
* A string containing attributes to be set for the drivers
* associated with the scheme. This should be in the form
* "protocol1:option1=value1;option2=value2,protocol2:option1=value1;
* option2=value2" Can be NULL if attributes are not being used.
*/
globus_result_t
globus_xio_handle_create_from_url(
globus_xio_handle_t * out_h,
const char * scheme,
globus_xio_attr_t attr,
char * param_string);
#ifdef __cplusplus
}
#endif
#endif
globus_xio-6.6/PaxHeaders.22691/globus_xio_wrapblock.h 0000644 0000000 0000000 00000000132 14243161125 021125 x ustar 00 0000000 0000000 30 mtime=1653400149.726966392
30 atime=1653401490.813550016
30 ctime=1653403998.729961713
globus_xio-6.6/globus_xio_wrapblock.h 0000664 0001750 0001750 00000003211 14243161125 021262 0 ustar 00johndoe johndoe 0000000 0000000 #if !defined(GLOBUS_XIO_WRAPBLOCK_H)
#define GLOBUS_XIO_WRAPBLOCK_H 1
#include "globus_xio.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef globus_result_t
(*globus_xio_wrapblock_open_func_t)(
const globus_xio_contact_t * contact_info,
void * driver_link,
void * driver_attr,
void ** driver_handle);
typedef globus_result_t
(*globus_xio_wrapblock_write_func_t)(
void * driver_specific_handle,
const globus_xio_iovec_t * iovec,
int iovec_count,
globus_size_t * nbytes);
typedef globus_result_t
(*globus_xio_wrapblock_read_func_t)(
void * driver_specific_handle,
const globus_xio_iovec_t * iovec,
int iovec_count,
globus_size_t * nbytes);
typedef globus_result_t
(*globus_xio_wrapblock_close_func_t)(
void * driver_specific_handle,
void * attr);
typedef globus_result_t
(*globus_xio_wrapblock_accept_func_t)(
void * driver_server,
void ** out_link);
globus_result_t
globus_xio_wrapblock_init(
globus_xio_driver_t driver,
globus_xio_wrapblock_open_func_t open,
globus_xio_wrapblock_close_func_t close,
globus_xio_wrapblock_read_func_t read,
globus_xio_wrapblock_write_func_t write,
globus_xio_wrapblock_accept_func_t accept);
#ifdef __cplusplus
}
#endif
#endif
globus_xio-6.6/PaxHeaders.22691/globus_xio_system.h 0000644 0000000 0000000 00000000132 14243161125 020465 x ustar 00 0000000 0000000 30 mtime=1653400149.724966412
30 atime=1653401470.566750347
30 ctime=1653403998.731961694
globus_xio-6.6/globus_xio_system.h 0000664 0001750 0001750 00000026610 14243161125 020632 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* The goal of this abstraction is to provide a common interface for the
* asynchronous and IO operations only.
*/
#ifndef GLOBUS_XIO_SYSTEM_INCLUDE
#define GLOBUS_XIO_SYSTEM_INCLUDE
#include "globus_common.h"
#include "globus_xio_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define GLOBUS_XIO_SYSTEM_MODULE (&globus_i_xio_system_module)
extern globus_module_descriptor_t globus_i_xio_system_module;
#ifdef WIN32
#include
#include
#define GLOBUS_XIO_SYSTEM_INVALID_FILE INVALID_HANDLE_VALUE
#define GLOBUS_XIO_SYSTEM_INVALID_SOCKET INVALID_SOCKET
typedef struct globus_l_xio_win32_file_s * globus_xio_system_file_handle_t;
typedef struct globus_l_xio_win32_socket_s * globus_xio_system_socket_handle_t;
typedef SOCKET globus_xio_system_socket_t;
typedef HANDLE globus_xio_system_file_t;
#else
#define GLOBUS_XIO_SYSTEM_INVALID_FILE -1
#define GLOBUS_XIO_SYSTEM_INVALID_SOCKET -1
/* these are handles to this interface */
typedef struct globus_l_xio_system_s * globus_xio_system_file_handle_t;
typedef struct globus_l_xio_system_s * globus_xio_system_socket_handle_t;
/* these are the native descriptor types */
typedef int globus_xio_system_socket_t;
typedef int globus_xio_system_file_t;
/* deprecated, do not use! */
typedef int globus_xio_system_native_handle_t;
#endif
typedef enum
{
GLOBUS_XIO_SYSTEM_ERROR_SYSTEM_ERROR = 1024,
GLOBUS_XIO_SYSTEM_ERROR_TOO_MANY_FDS,
GLOBUS_XIO_SYSTEM_ERROR_ALREADY_REGISTERED,
GLOBUS_XIO_SYSTEM_ERROR_OPERATION_CANCELED,
GLOBUS_XIO_SYSTEM_ERROR_NOT_REGISTERED
} globus_xio_system_error_type_t;
typedef enum
{
GLOBUS_XIO_SYSTEM_FILE = 1,
GLOBUS_XIO_SYSTEM_TCP,
GLOBUS_XIO_SYSTEM_TCP_LISTENER,
GLOBUS_XIO_SYSTEM_UDP
} globus_xio_system_type_t;
typedef void
(*globus_xio_system_callback_t)(
globus_result_t result,
void * user_arg);
typedef void
(*globus_xio_system_data_callback_t)(
globus_result_t result,
globus_size_t nbytes,
void * user_arg);
/**
* This handle is only used to maintain state for the operations below.
* As of now, the only modification it makes to the handle is set the
* non-blocking attribute.
*
* Note that initial file pointer is taken here and cached throughout.
* do not seek yourself
*/
globus_result_t
globus_xio_system_file_init(
globus_xio_system_file_handle_t * handle,
globus_xio_system_file_t fd);
/* this does *not* close the native handle.
* It should remove the non-blocking setting
*
* do not call this with outstanding operations. you can call it from with
* a callback
*/
void
globus_xio_system_file_destroy(
globus_xio_system_file_handle_t handle);
globus_result_t
globus_xio_system_file_register_read(
globus_xio_operation_t op,
globus_xio_system_file_handle_t handle,
globus_off_t offset,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t waitforbytes,
globus_xio_system_data_callback_t callback,
void * user_arg);
globus_result_t
globus_xio_system_file_register_write(
globus_xio_operation_t op,
globus_xio_system_file_handle_t handle,
globus_off_t offset,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t waitforbytes,
globus_xio_system_data_callback_t callback,
void * user_arg);
/* pass 0 for waitforbytes to not block */
globus_result_t
globus_xio_system_file_read(
globus_xio_system_file_handle_t handle,
globus_off_t offset,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t waitforbytes,
globus_size_t * nbytes);
globus_result_t
globus_xio_system_file_write(
globus_xio_system_file_handle_t handle,
globus_off_t offset,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t waitforbytes,
globus_size_t * nbytes);
/* syscall abstractions */
globus_off_t
globus_xio_system_file_get_position(
globus_xio_system_file_t fd);
globus_off_t
globus_xio_system_file_get_size(
globus_xio_system_file_t fd);
globus_xio_system_file_t
globus_xio_system_convert_stdio(
const char * stdio);
globus_result_t
globus_xio_system_file_truncate(
globus_xio_system_file_t fd,
globus_off_t size);
globus_result_t
globus_xio_system_file_open(
globus_xio_system_file_t * fd,
const char * filename,
int flags,
unsigned long mode);
globus_result_t
globus_xio_system_file_close(
globus_xio_system_file_t fd);
/**
* This handle is only used to maintain state for the operations below.
* As of now, the only modification it makes to the handle is set the
* non-blocking attribute.
*/
globus_result_t
globus_xio_system_socket_init(
globus_xio_system_socket_handle_t * handle,
globus_xio_system_socket_t socket,
globus_xio_system_type_t type);
/* this does *not* close the native handle.
* It should remove the non-blocking setting
*
* do not call this with outstanding operations. you can call it from with
* a callback
*/
void
globus_xio_system_socket_destroy(
globus_xio_system_socket_handle_t handle);
globus_result_t
globus_xio_system_socket_register_connect(
globus_xio_operation_t op,
globus_xio_system_socket_handle_t handle,
globus_sockaddr_t * addr,
globus_xio_system_callback_t callback,
void * user_arg);
globus_result_t
globus_xio_system_socket_register_accept(
globus_xio_operation_t op,
globus_xio_system_socket_handle_t listener_handle,
globus_xio_system_socket_t * out_handle,
globus_xio_system_callback_t callback,
void * user_arg);
/* if using from, probably want waitforbytes to be 1 */
/* if waitforbytes == 0 and iov[0].iov_len == 0
* behave like select()... ie notify when data ready
*/
globus_result_t
globus_xio_system_socket_register_read(
globus_xio_operation_t op,
globus_xio_system_socket_handle_t handle,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t waitforbytes,
int flags,
globus_sockaddr_t * out_from,
globus_xio_system_data_callback_t callback,
void * user_arg);
/* if waitforbytes == 0 and iov[0].iov_len == 0
* behave like select()... ie notify when data ready
*/
globus_result_t
globus_xio_system_socket_register_write(
globus_xio_operation_t op,
globus_xio_system_socket_handle_t handle,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t waitforbytes,
int flags,
globus_sockaddr_t * to,
globus_xio_system_data_callback_t callback,
void * user_arg);
/* if waitforbytes == 0, do a non-blocking read */
globus_result_t
globus_xio_system_socket_read(
globus_xio_system_socket_handle_t handle,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t waitforbytes,
int flags,
globus_sockaddr_t * from,
globus_size_t * nbytes);
/* if waitforbytes == 0, do a non-blocking write */
globus_result_t
globus_xio_system_socket_write(
globus_xio_system_socket_handle_t handle,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t waitforbytes,
int flags,
globus_sockaddr_t * to,
globus_size_t * nbytes);
/* syscall abstractions */
globus_result_t
globus_xio_system_socket_create(
globus_xio_system_socket_t * socket,
int domain,
int type,
int protocol);
globus_result_t
globus_xio_system_socket_setsockopt(
globus_xio_system_socket_t socket,
int level,
int optname,
const void * optval,
globus_socklen_t optlen);
globus_result_t
globus_xio_system_socket_getsockopt(
globus_xio_system_socket_t socket,
int level,
int optname,
void * optval,
globus_socklen_t * optlen);
globus_result_t
globus_xio_system_socket_getsockname(
globus_xio_system_socket_t socket,
struct sockaddr * name,
globus_socklen_t * namelen);
globus_result_t
globus_xio_system_socket_getpeername(
globus_xio_system_socket_t socket,
struct sockaddr * name,
globus_socklen_t * namelen);
globus_result_t
globus_xio_system_socket_bind(
globus_xio_system_socket_t socket,
struct sockaddr * addr,
globus_socklen_t addrlen);
globus_result_t
globus_xio_system_socket_listen(
globus_xio_system_socket_t socket,
int backlog);
globus_result_t
globus_xio_system_socket_connect(
globus_xio_system_socket_t socket,
const struct sockaddr * addr,
globus_socklen_t addrlen);
globus_result_t
globus_xio_system_socket_close(
globus_xio_system_socket_t socket);
#ifdef WIN32
/**
* XXX
* readonly on windows means something different than on unix. don't support
* it for now
*/
#undef S_IRWXU
#define S_IRWXU 0
#undef S_IRUSR
#define S_IRUSR 0
#undef S_IWUSR
#define S_IWUSR 0
#undef S_IXUSR
#define S_IXUSR 0
#undef S_IRWXO
#define S_IRWXO 0
#undef S_IROTH
#define S_IROTH 0
#undef S_IWOTH
#define S_IWOTH 0
#undef S_IXOTH
#define S_IXOTH 0
#undef S_IRWXG
#define S_IRWXG 0
#undef S_IRGRP
#define S_IRGRP 0
#undef S_IWGRP
#define S_IWGRP 0
#undef S_IXGRP
#define S_IXGRP 0
#endif
#ifdef __cplusplus
}
#endif
#endif
globus_xio-6.6/PaxHeaders.22691/globus_i_xio.h 0000644 0000000 0000000 00000000132 14243161125 017371 x ustar 00 0000000 0000000 30 mtime=1653400149.720966453
30 atime=1653401488.825569686
30 ctime=1653403998.732961685
globus_xio-6.6/globus_i_xio.h 0000664 0001750 0001750 00000107177 14243161125 017546 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
#if !defined(GLOBUS_I_XIO_H)
#define GLOBUS_I_XIO_H 1
#include "globus_xio.h"
#include "globus_xio_driver.h"
#include "globus_common.h"
#include "globus_xio_util.h"
#include "globus_xio_load.h"
#define GLOBUS_XIO_ATTR_ARRAY_BASE_SIZE 16
#define GLOBUS_XIO_HANDLE_DEFAULT_OPERATION_COUNT 4
/***************************************************************************
* internal macros
* ---------------
**************************************************************************/
#define GlobusXIOCurrentBlockedThread(blocked_thread) \
if (globus_i_am_only_thread()) \
{ \
blocked_thread.thread = globus_thread_self(); \
} \
else \
{ \
blocked_thread.depth = globus_callback_space_get_depth( \
GLOBUS_CALLBACK_GLOBAL_SPACE); \
}
#define GlobusXIOBlockedThreadMatchesCurrentThread(a) \
(globus_i_am_only_thread() \
? (a.depth == \
globus_callback_space_get_depth(GLOBUS_CALLBACK_GLOBAL_SPACE)) \
: globus_thread_equal(a.thread, globus_thread_self()))
GlobusDebugDeclare(GLOBUS_XIO);
#define GlobusXIODebugPrintf(level, message) \
GlobusDebugPrintf(GLOBUS_XIO, level, message)
#define GlobusXIOOpInc(_in_op) \
do \
{ \
(_in_op)->ref++; \
GlobusXIODebugPrintf( \
GLOBUS_XIO_DEBUG_STATE, \
("[%s:%d] Op @ 0x%x ref increased to %d:\n", _xio_name, __LINE__, \
(_in_op), (_in_op)->ref)); \
} while(0)
#define GlobusXIOOpDec(_in_op) \
do \
{ \
(_in_op)->ref--; \
GlobusXIODebugPrintf( \
GLOBUS_XIO_DEBUG_STATE, \
("[%s:%d] Op @ 0x%x ref decreased to %d:\n", _xio_name, __LINE__, \
(_in_op), (_in_op)->ref)); \
} while(0)
#define GlobusXIOObjToResult(_in_obj) \
(_in_obj == NULL ? GLOBUS_SUCCESS : globus_error_put(_in_obj))
#define GlobusXIOResultToObj(_in_res) \
(_in_res == GLOBUS_SUCCESS ? NULL : globus_error_get(_in_res))
#define GlobusXIOHandleStateChange(_h, _new) \
do \
{ \
globus_i_xio_handle_t * _l_h; \
\
_l_h = (_h); \
GlobusXIODebugPrintf( \
GLOBUS_XIO_DEBUG_STATE, \
("[%s:%d] Handle @ 0x%x state change:\n" \
" From:%s\n" \
" to: %s\n", \
_xio_name, \
__LINE__, \
_l_h, \
globus_i_xio_handle_state_name_table[_l_h->state], \
globus_i_xio_handle_state_name_table[_new])); \
_l_h->state = _new; \
} while(0)
#define GlobusXIOOpStateChange(_op, _new) \
do \
{ \
globus_i_xio_op_t * _l_op; \
\
_l_op = (_op); \
GlobusXIODebugPrintf( \
GLOBUS_XIO_DEBUG_STATE, \
("[%s:%d] Op @ 0x%x state change:\n" \
" From:%s\n" \
" to: %s\n", \
_xio_name, \
__LINE__, \
_l_op, \
globus_i_xio_op_state_name_table[_l_op->state], \
globus_i_xio_op_state_name_table[_new])); \
_l_op->state = _new; \
} while(0)
#define GlobusXIOContextStateChange(_c, _new) \
do \
{ \
globus_i_xio_context_entry_t * _l_context; \
\
_l_context = (_c); \
GlobusXIODebugPrintf( \
GLOBUS_XIO_DEBUG_STATE, \
("[%s:%d] Context @ 0x%x state change:\n" \
" From:%s\n" \
" to: %s\n", \
_xio_name, \
__LINE__, \
_l_context, \
globus_i_xio_context_state_name_table[_l_context->state], \
globus_i_xio_context_state_name_table[_new])); \
_l_context->state = _new; \
} while(0)
#define GlobusXIODebugEnter() \
GlobusXIODebugPrintf( \
GLOBUS_XIO_DEBUG_TRACE, \
("[%s] Entering\n", _xio_name))
#define GlobusXIODebugExit() \
GlobusXIODebugPrintf( \
GLOBUS_XIO_DEBUG_TRACE, \
("[%s] Exiting\n", _xio_name))
#define GlobusXIODebugExitWithError() \
GlobusXIODebugPrintf( \
GLOBUS_XIO_DEBUG_TRACE, \
("[%s] Exiting with error\n", _xio_name))
#define GlobusXIODebugInternalEnter() \
GlobusXIODebugPrintf( \
GLOBUS_XIO_DEBUG_INTERNAL_TRACE, \
("[%s] I Entering\n", _xio_name))
#define GlobusXIODebugInternalExit() \
GlobusXIODebugPrintf( \
GLOBUS_XIO_DEBUG_INTERNAL_TRACE, \
("[%s] I Exiting\n", _xio_name))
#define GlobusXIODebugInternalExitWithError() \
GlobusXIODebugPrintf( \
GLOBUS_XIO_DEBUG_INTERNAL_TRACE, \
("[%s] I Exiting with error\n", _xio_name))
#define GlobusXIODebugInregisterOneShot() \
GlobusXIODebugPrintf( \
GLOBUS_XIO_DEBUG_INFO, \
("[%s] Registering one shot due to in_register.\n", _xio_name))
#define GlobusXIODebugDelayedFinish() \
GlobusXIODebugPrintf( \
GLOBUS_XIO_DEBUG_INFO, \
("[%s] Delaying finish due to in_register and blocking op.\n", \
_xio_name))
#define GlobusXIOOperationCreate(_out_op, _in_c) \
do \
{ \
globus_i_xio_op_t * _X_op; \
globus_i_xio_context_t * _X_c; \
\
_X_c = (_in_c); \
_X_op = (globus_i_xio_op_t * ) \
globus_memory_pop_node(&_X_c->op_memory); \
if(_X_op != NULL) \
{ \
/* sets deliver_op to NONE */ \
memset(_X_op, '\0', sizeof(globus_i_xio_op_t) + \
(sizeof(globus_i_xio_op_entry_t) * (_X_c->stack_size - 1))); \
_X_op->_op_context = _X_c; \
_X_op->stack_size = _X_c->stack_size; \
_X_op->progress = GLOBUS_TRUE; \
_X_op->_op_ent_offset = -1; \
} \
_out_op = _X_op; \
} while(0)
/* if index == the level at which a cancel was requested then we reset the
* canceled flag for the operation.
*/
#define GlobusIXIOClearCancel(op) \
do \
{ \
globus_i_xio_op_t * _op = (op); \
/* op->ndx is source_ndx + 1, canceled is source_ndx + 2 */ \
/* so, source_ndx == op->ndx + 1 */ \
/* see globus_i_xio_operation_cancel */ \
if(_op->canceled) \
{ \
globus_mutex_lock(&_op->_op_context->cancel_mutex); \
if(_op->canceled == _op->ndx + 1) \
{ \
_op->canceled = 0; \
} \
globus_mutex_unlock(&_op->_op_context->cancel_mutex); \
} \
} while(0)
/***************************************************************************
* state and type enumerations
* ---------------------------
**************************************************************************/
/* forward declare for setting cred */
typedef struct gss_cred_id_desc_struct * gss_cred_id_t;
extern char * globus_i_xio_context_state_name_table[];
typedef enum globus_i_xio_context_state_e
{
GLOBUS_XIO_CONTEXT_STATE_NONE,
GLOBUS_XIO_CONTEXT_STATE_OPENING,
GLOBUS_XIO_CONTEXT_STATE_OPEN,
GLOBUS_XIO_CONTEXT_STATE_OPEN_FAILED,
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED,
GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED,
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED_AND_CLOSING,
GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED_AND_CLOSING,
GLOBUS_XIO_CONTEXT_STATE_CLOSING,
GLOBUS_XIO_CONTEXT_STATE_OPENING_AND_CLOSING,
GLOBUS_XIO_CONTEXT_STATE_CLOSED
} globus_i_xio_context_state_t;
extern char * globus_i_xio_handle_state_name_table[];
typedef enum globus_i_xio_handle_state_e
{
GLOBUS_XIO_HANDLE_STATE_NONE,
GLOBUS_XIO_HANDLE_STATE_CLIENT,
GLOBUS_XIO_HANDLE_STATE_ACCEPTED,
GLOBUS_XIO_HANDLE_STATE_OPENING,
GLOBUS_XIO_HANDLE_STATE_OPENING_FAILED,
GLOBUS_XIO_HANDLE_STATE_OPENING_AND_CLOSING,
GLOBUS_XIO_HANDLE_STATE_OPEN,
GLOBUS_XIO_HANDLE_STATE_OPEN_FAILED,
GLOBUS_XIO_HANDLE_STATE_CLOSING,
GLOBUS_XIO_HANDLE_STATE_CLOSED
} globus_i_xio_handle_state_t;
extern char * globus_i_xio_op_state_name_table[];
typedef enum globus_i_xio_op_state_e
{
GLOBUS_XIO_OP_STATE_NONE,
GLOBUS_XIO_OP_STATE_OPERATING,
GLOBUS_XIO_OP_STATE_TIMEOUT_PENDING,
GLOBUS_XIO_OP_STATE_FINISH_WAITING,
GLOBUS_XIO_OP_STATE_FINISHED
} globus_i_xio_op_state_t;
typedef enum globus_xio_server_state_e
{
GLOBUS_XIO_SERVER_STATE_NONE,
GLOBUS_XIO_SERVER_STATE_OPEN,
GLOBUS_XIO_SERVER_STATE_ACCEPTING,
GLOBUS_XIO_SERVER_STATE_COMPLETING,
GLOBUS_XIO_SERVER_STATE_CLOSE_PENDING,
GLOBUS_XIO_SERVER_STATE_CLOSING,
GLOBUS_XIO_SERVER_STATE_CLOSED
} globus_xio_server_state_t;
/***************************************************************************
* Internally exposed data structures
* ----------------------------------
**************************************************************************/
struct globus_i_xio_context_s;
struct globus_i_xio_op_s;
typedef struct globus_i_xio_monitor_s
{
int count;
} globus_i_xio_monitor_t;
void
globus_i_xio_monitor_init(
globus_i_xio_monitor_t * monitor);
void
globus_i_xio_monitor_destroy(
globus_i_xio_monitor_t * monitor);
typedef struct globus_i_xio_attr_ent_s
{
globus_xio_driver_t driver;
void * driver_data;
} globus_i_xio_attr_ent_t;
typedef struct globus_i_xio_attr_s
{
globus_bool_t unloaded;
globus_xio_timeout_callback_t open_timeout_cb;
globus_reltime_t open_timeout_period;
globus_xio_timeout_callback_t read_timeout_cb;
globus_reltime_t read_timeout_period;
globus_xio_timeout_callback_t write_timeout_cb;
globus_reltime_t write_timeout_period;
globus_xio_timeout_callback_t close_timeout_cb;
globus_reltime_t close_timeout_period;
globus_xio_timeout_server_callback_t accept_timeout_cb;
globus_reltime_t accept_timeout_period;
globus_bool_t cancel_open;
globus_bool_t cancel_close;
globus_bool_t cancel_read;
globus_bool_t cancel_write;
globus_bool_t no_cancel;
void * timeout_arg;
gss_cred_id_t user_open_cred;
char * user_open_sbj;
char * user_open_username;
char * user_open_pw;
globus_callback_space_t space;
int max;
int ndx;
globus_i_xio_attr_ent_t * entry;
} globus_i_xio_attr_t;
typedef struct globus_i_xio_stack_s
{
int size;
globus_list_t * driver_stack;
globus_xio_driver_t pushing_driver;
} globus_i_xio_stack_t;
typedef struct globus_i_xio_server_entry_s
{
globus_xio_driver_t driver;
void * server_handle;
} globus_i_xio_server_entry_t;
/*
*
*/
typedef struct globus_i_xio_server_s
{
globus_i_xio_monitor_t * sd_monitor;
globus_xio_server_state_t state;
globus_xio_timeout_server_callback_t accept_timeout;
globus_reltime_t accept_timeout_period;
struct globus_i_xio_op_s * op;
globus_xio_server_callback_t cb;
void * user_arg;
int outstanding_operations;
int ref;
globus_mutex_t mutex;
globus_callback_space_t space;
globus_bool_t blocking;
char * contact_string;
int stack_size;
globus_i_xio_server_entry_t entry[1];
} globus_i_xio_server_t;
typedef struct globus_i_xio_handle_s
{
globus_i_xio_monitor_t * sd_monitor;
globus_list_t * cb_list;
int ref;
struct globus_i_xio_context_s * context;
globus_i_xio_handle_state_t state;
/* since only 1 open or close can be outstanding at a time we don't
need a list */
globus_list_t * write_op_list;
globus_list_t * read_op_list;
struct globus_i_xio_op_s * open_op;
struct globus_i_xio_op_s * close_op;
void * timeout_arg;
globus_callback_space_t space;
globus_xio_timeout_callback_t open_timeout_cb;
globus_reltime_t open_timeout_period;
globus_xio_timeout_callback_t read_timeout_cb;
globus_reltime_t read_timeout_period;
globus_xio_timeout_callback_t write_timeout_cb;
globus_reltime_t write_timeout_period;
globus_xio_timeout_callback_t close_timeout_cb;
globus_reltime_t close_timeout_period;
} globus_i_xio_handle_t;
/*
* represents an entry in the array of open handles.
*
* each entry is mapped to a driver in the stack
*/
typedef struct globus_i_xio_context_entry_s
{
globus_xio_driver_t driver;
void * driver_handle;
/* each level must implement the entire state machine */
globus_i_xio_context_state_t state;
int outstanding_operations;
int read_operations;
int eof_operations;
int pending_reads;
/* is this hacky? */
globus_bool_t close_started;
struct globus_i_xio_op_s * open_op;
struct globus_i_xio_op_s * close_op;
globus_list_t * eof_op_list;
globus_fifo_t pending_read_queue;
struct globus_i_xio_context_s * whos_my_daddy;
} globus_i_xio_context_entry_t;
/*
* a stretchy array
*/
typedef struct globus_i_xio_context_s
{
/* handle has a reference and every entry has a reference */
int ref;
int stack_size;
globus_memory_t op_memory;
globus_mutex_t mutex;
globus_mutex_t cancel_mutex;
globus_i_xio_context_entry_t entry[1];
} globus_i_xio_context_t;
/* MACROS for accessing the op_entry structure unin elements */
#define _op_ent_data_cb type_u.handle_s.data_cb
#define _op_ent_wait_for type_u.handle_s.wait_for_bytes
#define _op_ent_offset type_u.handle_s.offset
#define _op_ent_nbytes type_u.handle_s.nbytes
#define _op_ent_iovec type_u.handle_s.iovec
#define _op_ent_iovec_count type_u.handle_s.iovec_count
#define _op_ent_fake_iovec type_u.handle_s.fake_iovec
/*
* represents a entry in an array of operations. Each entry
* is mapped to a driver at the same index.
*/
typedef struct globus_i_xio_op_entry_s
{
/* callback info arrays */
globus_xio_operation_type_t type;
globus_xio_driver_callback_t cb;
void * user_arg;
union
{
/* handle op entries */
struct
{
globus_xio_driver_data_callback_t data_cb;
globus_size_t wait_for_bytes;
globus_size_t nbytes;
globus_xio_iovec_t * iovec;
int iovec_count;
globus_xio_iovec_t * fake_iovec;
} handle_s;
} type_u;
globus_bool_t in_register;
globus_bool_t is_limited;
void * dd;
void * link;
void * open_attr;
void * close_attr;
int prev_ndx;
int next_ndx;
globus_xio_operation_type_t * deliver_type;
} globus_i_xio_op_entry_t;
#define _op_data_cb data_cb
#define _op_iovec_cb iovec_cb
#define _op_cb callback_u.cb
#define _op_accept_cb callback_u.accept_cb
#define _op_handle type_u.handle_s.handle
#define _op_iovec type_u.handle_s.iovec
#define _op_iovec_count type_u.handle_s.iovec_count
#define _op_mem_iovec type_u.handle_s.mem_iovec
#define _op_context type_u.handle_s.context
#define _op_nbytes type_u.handle_s.nbytes
#define _op_wait_for type_u.handle_s.wait_for
#define _op_handle_timeout_cb type_u.handle_s.timeout_cb
#define _op_server type_u.server_s.server
#define _op_server_timeout_cb type_u.server_s.timeout_cb
/**
* @brief Information about the what thread is being blocked by a callback.
*
* In the non-threaded case, this will be the callback_depth, otherwise
* the thread_id
*/
typedef union
{
globus_thread_t thread;
int depth;
}
globus_i_xio_blocked_thread_t;
/*
* represents a requested io operation (open close read or write).
*/
typedef struct globus_i_xio_op_s
{
/* operation type */
globus_xio_operation_type_t type;
globus_i_xio_op_state_t state;
globus_bool_t is_user_dd;
/*
* user callbacks. only 1 will be used per operation
*/
union
{
globus_xio_callback_t cb;
globus_xio_accept_callback_t accept_cb;
}callback_u;
globus_xio_data_callback_t data_cb;
globus_xio_iovec_callback_t iovec_cb;
void * user_arg;
/*
* Union operation members that will not overlap together
*/
union
{
/* handle op stuff */
struct
{
globus_i_xio_handle_t * handle;
globus_xio_iovec_t * iovec;
int iovec_count;
globus_xio_iovec_t mem_iovec;
globus_size_t nbytes;
/* convenience pointer, really owned by handle */
globus_i_xio_context_t * context;
/* data descriptor */
globus_size_t wait_for;
globus_off_t offset;
globus_xio_timeout_callback_t timeout_cb;
} handle_s;
/* server op stuff */
struct
{
globus_i_xio_server_t * server;
globus_xio_timeout_server_callback_t timeout_cb;
} server_s;
} type_u;
/* flag to determine if timeout should happen */
globus_bool_t progress;
/* reference count for destruction */
int ref;
/* members for cancellation */
globus_xio_driver_cancel_callback_t cancel_cb;
void * cancel_arg;
int canceled;
globus_bool_t block_timeout;
globus_bool_t restarted;
globus_bool_t blocking;
globus_i_xio_blocked_thread_t blocked_thread;
globus_bool_t finished_delayed;
/* just stash away the cred to open so that the driver can interrogate
it. */
gss_cred_id_t user_open_cred;
char * user_open_sbj;
char * user_open_username;
char * user_open_pw;
/* result code saved in op for kickouts */
globus_object_t * cached_obj;
/* size of the arrays */
int stack_size;
/* current index in the driver stack */
int ndx;
/* entry for each thing driver in the stack */
globus_i_xio_op_entry_t entry[1];
} globus_i_xio_op_t;
typedef struct globus_i_xio_driver_s
{
char * name;
void * user_data;
void * wrap_data;
/* these are filled in by the driver loader */
globus_xio_driver_hook_t * hook;
globus_extension_handle_t extension_handle;
globus_bool_t extension_activated;
globus_xio_string_cntl_table_t * string_table;
globus_xio_string_cntl_table_t * handle_string_table;
/*
* main io interface functions
*/
globus_xio_driver_transform_open_t transform_open_func;
globus_xio_driver_transport_open_t transport_open_func;
globus_xio_driver_close_t close_func;
globus_xio_driver_read_t read_func;
globus_xio_driver_write_t write_func;
globus_xio_driver_handle_cntl_t handle_cntl_func;
globus_xio_driver_push_driver_t push_driver_func;
/*
* server
*/
globus_xio_driver_server_init_t server_pre_init_func;
globus_xio_driver_server_init_t server_init_func;
globus_xio_driver_server_accept_t server_accept_func;
globus_xio_driver_server_destroy_t server_destroy_func;
globus_xio_driver_server_cntl_t server_cntl_func;
globus_xio_driver_link_cntl_t link_cntl_func;
globus_xio_driver_link_destroy_t link_destroy_func;
/*
* driver attr functions. All or none may be NULL
*
* data descriptor is done with attr
*/
globus_xio_driver_attr_init_t attr_init_func;
globus_xio_driver_attr_copy_t attr_copy_func;
globus_xio_driver_attr_cntl_t attr_cntl_func;
globus_xio_driver_attr_destroy_t attr_destroy_func;
} globus_i_xio_driver_t;
/*
* wrapper struct
*/
typedef struct globus_i_xio_blocking_s
{
globus_mutex_t mutex;
globus_cond_t cond;
globus_bool_t done;
globus_size_t nbytes;
globus_i_xio_op_t * op;
globus_xio_handle_t accepted_handle;
globus_xio_data_descriptor_t data_desc;
globus_object_t * error_obj;
} globus_i_xio_blocking_t;
typedef struct globus_i_xio_restart_s
{
globus_i_xio_op_t * op;
globus_bool_t restarted;
} globus_i_xio_restart_t;
globus_i_xio_blocking_t *
globus_i_xio_blocking_alloc();
void
globus_i_xio_blocking_destroy(
globus_i_xio_blocking_t * info);
/*************************************************************************
* internal function signatures
************************************************************************/
globus_result_t
globus_i_xio_server_close(
globus_xio_server_t xio_server,
globus_xio_server_callback_t cb,
void * user_arg);
void
globus_l_xio_driver_purge_read_eof(
globus_i_xio_context_entry_t * my_context);
void
globus_l_xio_driver_op_write_kickout(
void * user_arg);
void
globus_l_xio_driver_op_read_kickout(
void * user_arg);
globus_result_t
globus_i_xio_driver_start_close(
globus_i_xio_op_t * op,
globus_bool_t can_fail);
void
globus_l_xio_driver_op_close_kickout(
void * user_arg);
void
globus_l_xio_driver_op_accept_kickout(
void * user_arg);
void
globus_l_xio_driver_open_op_kickout(
void * user_arg);
void
globus_i_xio_driver_resume_op(
globus_i_xio_op_t * op);
/*
* time stuff
*/
typedef globus_bool_t
(*globus_i_xio_timer_cb_t)(
void * datum);
typedef struct globus_i_xio_op_timer_s
{
globus_reltime_t minimal_delay;
globus_mutex_t mutex;
globus_cond_t cond;
globus_list_t * op_list;
globus_bool_t running;
globus_callback_handle_t periodic_handle;
} globus_i_xio_timer_t;
void
globus_i_xio_timer_init(
globus_i_xio_timer_t * timer);
void
globus_i_xio_timer_destroy(
globus_i_xio_timer_t * timer);
void
globus_i_xio_timer_register_timeout(
globus_i_xio_timer_t * timer,
void * datum,
globus_bool_t * progress_ptr,
globus_i_xio_timer_cb_t timeout_cb,
globus_reltime_t * timeout);
globus_bool_t
globus_i_xio_timer_unregister_timeout(
globus_i_xio_timer_t * timer,
void * datum);
globus_i_xio_context_t *
globus_i_xio_context_create(
int stack_size);
void
globus_i_xio_context_destroy(
globus_i_xio_context_t * xio_context);
void
globus_i_xio_will_block_cb(
int space,
globus_thread_callback_index_t ndx,
void * user_args);
void
globus_i_xio_pass_failed(
globus_i_xio_op_t * op,
globus_i_xio_context_entry_t * my_context,
globus_bool_t * close,
globus_bool_t * destroy_handle);
void
globus_i_xio_handle_destroy(
globus_i_xio_handle_t * handle);
void
globus_i_xio_handle_dec(
globus_i_xio_handle_t * handle,
globus_bool_t * destroy_handle);
void
globus_i_xio_op_destroy(
globus_i_xio_op_t * op,
globus_bool_t * destroy_handle);
globus_result_t
globus_i_xio_repass_write(
globus_i_xio_op_t * op);
globus_result_t
globus_i_xio_repass_read(
globus_i_xio_op_t * op);
void
globus_i_xio_register_oneshot(
globus_i_xio_handle_t * handle,
globus_callback_func_t cb,
void * user_arg,
globus_callback_space_t space);
typedef struct globus_i_xio_space_info_s
{
globus_bool_t unregister;
globus_i_xio_handle_t * handle;
globus_callback_handle_t ch;
globus_callback_func_t func;
void * user_arg;
} globus_i_xio_space_info_t;
void
globus_i_xio_close_handles(
globus_xio_driver_t driver);
globus_result_t
globus_i_xio_operation_cancel(
globus_i_xio_op_t * op,
int source_ndx);
void
globus_i_xio_driver_deliver_op(
globus_i_xio_op_t * op,
int ndx,
globus_xio_operation_type_t deliver_type);
void
globus_xio_driver_open_delivered(
globus_xio_operation_t in_op,
int in_ndx,
globus_xio_operation_type_t * deliver_type);
void
globus_xio_driver_write_delivered(
globus_xio_operation_t in_op,
int in_ndx,
globus_xio_operation_type_t * deliver_type);
void
globus_xio_driver_read_delivered(
globus_xio_operation_t op,
int in_ndx,
globus_xio_operation_type_t * deliver_type);
globus_result_t
globus_i_xio_driver_dd_cntl(
globus_i_xio_op_t * op,
globus_xio_driver_t driver,
globus_xio_operation_type_t type,
int cmd,
va_list ap);
globus_result_t
globus_i_xio_driver_handle_cntl(
globus_i_xio_context_t * context,
int start_ndx,
globus_xio_driver_t driver,
int cmd,
va_list ap);
globus_result_t
globus_i_xio_driver_attr_cntl(
globus_i_xio_attr_t * attr,
globus_xio_driver_t driver,
int cmd,
va_list ap);
globus_result_t
globus_i_xio_string_cntl_parser(
const char * env_str,
globus_xio_string_cntl_table_t * table,
void * attr,
globus_xio_driver_attr_cntl_t attr_func);
extern globus_i_xio_timer_t globus_i_xio_timeout_timer;
extern globus_list_t * globus_i_xio_outstanding_handles_list;
extern globus_list_t * globus_i_xio_outstanding_servers_list;
extern globus_list_t * globus_i_xio_outstanding_attrs_list;
extern globus_list_t * globus_i_xio_outstanding_dds_list;
extern globus_mutex_t globus_i_xio_mutex;
extern globus_cond_t globus_i_xio_cond;
#endif /* GLOBUS_I_XIO_H */
#endif /* GLOBUS_DONT_DOCUMENT_INTERNAL */
globus_xio-6.6/PaxHeaders.22691/globus_i_xio_system_common.h 0000644 0000000 0000000 00000000131 14243161125 022344 x ustar 00 0000000 0000000 30 mtime=1653400149.720966453
29 atime=1653401490.94854868
30 ctime=1653403998.734961666
globus_xio-6.6/globus_i_xio_system_common.h 0000664 0001750 0001750 00000040213 14243161125 022505 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GLOBUS_I_XIO_SYSTEM_COMMON_INCLUDE
#define GLOBUS_I_XIO_SYSTEM_COMMON_INCLUDE
#include "globus_i_xio_config.h"
#include "globus_common.h"
#include "globus_xio_system.h"
#include "globus_xio_driver.h"
GlobusDebugDeclare(GLOBUS_XIO_SYSTEM);
#define GlobusXIOSystemDebugPrintf(level, message) \
GlobusDebugPrintf(GLOBUS_XIO_SYSTEM, level, message)
#define GlobusXIOSystemDebugFwrite(level, buffer, size, count) \
GlobusDebugFwrite(GLOBUS_XIO_SYSTEM, level, buffer, size, count)
#define GlobusXIOSystemDebugEnter() \
GlobusXIOSystemDebugPrintf( \
GLOBUS_I_XIO_SYSTEM_DEBUG_TRACE, \
("[%s] Entering\n", _xio_name))
#define GlobusXIOSystemDebugExit() \
GlobusXIOSystemDebugPrintf( \
GLOBUS_I_XIO_SYSTEM_DEBUG_TRACE, \
("[%s] Exiting\n", _xio_name))
#define GlobusXIOSystemDebugExitWithError() \
GlobusXIOSystemDebugPrintf( \
GLOBUS_I_XIO_SYSTEM_DEBUG_TRACE, \
("[%s] Exiting with error\n", _xio_name))
#define GlobusXIOSystemDebugEnterFD(fd) \
GlobusXIOSystemDebugPrintf( \
GLOBUS_I_XIO_SYSTEM_DEBUG_TRACE, \
("[%s] fd=%lu, Entering\n", _xio_name, (unsigned long)(fd)))
#define GlobusXIOSystemDebugExitFD(fd) \
GlobusXIOSystemDebugPrintf( \
GLOBUS_I_XIO_SYSTEM_DEBUG_TRACE, \
("[%s] fd=%lu, Exiting\n", _xio_name, (unsigned long)(fd)))
#define GlobusXIOSystemDebugExitWithErrorFD(fd) \
GlobusXIOSystemDebugPrintf( \
GLOBUS_I_XIO_SYSTEM_DEBUG_TRACE, \
("[%s] fd=%lu, Exiting with error\n", _xio_name, (unsigned long)(fd)))
#ifdef WIN32
#include
#define GlobusXIOSystemUpdateErrno() (errno = WSAGetLastError())
#else
#define GlobusXIOSystemUpdateErrno()
#endif
#define GlobusXIOSystemDebugRawBuffer(nbytes, buffer) \
do \
{ \
GlobusXIOSystemDebugPrintf( \
GLOBUS_I_XIO_SYSTEM_DEBUG_RAW, \
("[%s] Begin RAW data ************\n", _xio_name)); \
GlobusXIOSystemDebugFwrite( \
GLOBUS_I_XIO_SYSTEM_DEBUG_RAW, buffer, 1, nbytes); \
GlobusXIOSystemDebugPrintf( \
GLOBUS_I_XIO_SYSTEM_DEBUG_RAW, \
("\n[%s] End RAW data ************\n", _xio_name)); \
} while(0)
#define GlobusXIOSystemDebugRawIovec(nbytes, iovec) \
do \
{ \
if(GlobusDebugTrue( \
GLOBUS_XIO_SYSTEM, GLOBUS_I_XIO_SYSTEM_DEBUG_RAW)) \
{ \
globus_size_t _bytes = nbytes; \
int _i = 0; \
\
while(_bytes > 0) \
{ \
globus_size_t _len = (iovec)[_i].iov_len; \
\
if(_bytes < _len) \
{ \
_len = _bytes; \
} \
_bytes -= _len; \
\
GlobusDebugMyPrintf( \
GLOBUS_XIO_SYSTEM, \
("[%s] Begin RAW data %i ************\n", \
_xio_name, _i)); \
GlobusDebugMyFwrite( \
GLOBUS_XIO_SYSTEM, \
(iovec)[_i].iov_base, 1, _len); \
GlobusDebugMyPrintf( \
GLOBUS_XIO_SYSTEM, \
("\n[%s] End RAW data %i ************\n", \
_xio_name, _i)); \
_i++; \
} \
} \
} while(0)
#define GlobusIXIOSystemAllocOperation(op_info) \
do \
{ \
globus_i_xio_system_op_info_t * _op_info; \
\
_op_info = (globus_i_xio_system_op_info_t *) \
globus_memory_pop_node(&globus_i_xio_system_op_info_memory); \
if(_op_info) \
{ \
memset(_op_info, 0, sizeof(globus_i_xio_system_op_info_t)); \
} \
(op_info) = _op_info; \
} while(0)
#define GlobusIXIOSystemFreeOperation(op_info) \
(globus_memory_push_node(&globus_i_xio_system_op_info_memory, (op_info)))
#define GlobusIXIOSystemAllocIovec(count, iov) \
do \
{ \
int _count; \
\
_count = (count); \
\
if(_count < 10) \
{ \
(iov) = (struct iovec *) \
globus_memory_pop_node(&globus_i_xio_system_iov_memory); \
} \
else \
{ \
(iov) = (struct iovec *) \
globus_malloc(sizeof(struct iovec) * _count); \
} \
} while(0)
#define GlobusIXIOSystemFreeIovec(count, iovec) \
do \
{ \
int _count = (count); \
if(_count < 10) \
{ \
globus_memory_push_node( \
&globus_i_xio_system_iov_memory, (iovec)); \
} \
else \
{ \
globus_free((iovec)); \
} \
} while(0)
extern globus_memory_t globus_i_xio_system_op_info_memory;
extern globus_memory_t globus_i_xio_system_iov_memory;
enum globus_i_xio_system_error_levels
{
GLOBUS_I_XIO_SYSTEM_DEBUG_TRACE = 1,
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA = 2,
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO = 4,
GLOBUS_I_XIO_SYSTEM_DEBUG_RAW = 8
};
typedef enum
{
GLOBUS_I_XIO_SYSTEM_OP_ACCEPT,
GLOBUS_I_XIO_SYSTEM_OP_CONNECT,
GLOBUS_I_XIO_SYSTEM_OP_READ,
GLOBUS_I_XIO_SYSTEM_OP_WRITE
} globus_i_xio_system_op_type_t;
typedef enum
{
/* initial state */
GLOBUS_I_XIO_SYSTEM_OP_NEW,
/* transition to this requires fdset lock */
GLOBUS_I_XIO_SYSTEM_OP_PENDING,
/* transition to this requires cancel lock */
GLOBUS_I_XIO_SYSTEM_OP_COMPLETE,
/* transition to this requires fdset and cancel lock */
GLOBUS_I_XIO_SYSTEM_OP_CANCELED
} globus_i_xio_system_op_state_t;
#if defined(_WIN32)
struct msghdr
{
void * msg_name;
int msg_namelen;
struct iovec * msg_iov;
int msg_iovlen;
void * msg_control;
int msg_controllen;
int msg_flags;
};
#endif
typedef struct
{
/* common members */
globus_i_xio_system_op_type_t type;
globus_i_xio_system_op_state_t state;
globus_xio_operation_t op;
#ifndef WIN32
struct globus_l_xio_system_s * handle;
#else
struct globus_l_xio_win32_socket_s *handle;
#endif
globus_object_t * error;
void * user_arg;
/* used for reads/writes, 0 for others. here to simplify some things */
globus_size_t nbytes;
globus_size_t waitforbytes;
globus_off_t offset;
union
{
/* non data ops -- connect, accept */
struct
{
globus_xio_system_callback_t callback;
globus_xio_system_socket_t * out_fd;
} non_data;
/* data ops */
struct
{
globus_xio_system_data_callback_t callback;
struct iovec * start_iov;
int start_iovc;
struct iovec * iov;
int iovc;
globus_sockaddr_t * addr;
int flags;
} data;
} sop;
} globus_i_xio_system_op_info_t;
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_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_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_result_t
globus_i_xio_system_try_recvfrom(
globus_xio_system_socket_t fd,
void * buf,
globus_size_t buflen,
int flags,
globus_sockaddr_t * from,
globus_size_t * nbytes);
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_result_t
globus_i_xio_system_try_write(
globus_xio_system_file_t fd,
void * buf,
globus_size_t buflen,
globus_size_t * nbytes);
globus_result_t
globus_i_xio_system_try_writev(
globus_xio_system_file_t fd,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t * nbytes);
globus_result_t
globus_i_xio_system_try_send(
globus_xio_system_socket_t fd,
void * buf,
globus_size_t buflen,
int flags,
globus_size_t * nbytes);
globus_result_t
globus_i_xio_system_try_sendto(
globus_xio_system_socket_t fd,
void * buf,
globus_size_t buflen,
int flags,
const globus_sockaddr_t * to,
globus_size_t * nbytes);
globus_result_t
globus_i_xio_system_try_sendmsg(
globus_xio_system_socket_t fd,
struct msghdr * msghdr,
int flags,
globus_size_t * nbytes);
globus_result_t
globus_i_xio_system_file_try_read(
globus_xio_system_file_t handle,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t * nbytes);
globus_result_t
globus_i_xio_system_file_try_write(
globus_xio_system_file_t handle,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t * nbytes);
globus_result_t
globus_i_xio_system_socket_try_read(
globus_xio_system_socket_t handle,
const globus_xio_iovec_t * iov,
int iovc,
int flags,
globus_sockaddr_t * from,
globus_size_t * nbytes);
globus_result_t
globus_i_xio_system_socket_try_write(
globus_xio_system_socket_t handle,
const globus_xio_iovec_t * iov,
int iovc,
int flags,
globus_sockaddr_t * to,
globus_size_t * nbytes);
int
globus_i_xio_system_common_activate(void);
int
globus_i_xio_system_common_deactivate(void);
#endif
globus_xio-6.6/PaxHeaders.22691/globus_xio_handle.c 0000644 0000000 0000000 00000000132 14243161125 020367 x ustar 00 0000000 0000000 30 mtime=1653400149.723966423
30 atime=1653401488.307574811
30 ctime=1653403998.746961551
globus_xio-6.6/globus_xio_handle.c 0000664 0001750 0001750 00000345766 14243161125 020554 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "globus_xio.h"
#include "globus_i_xio.h"
/*
* read_op_list adn write_op_list
* ------------------------------
* list of operations whos callbacks have not yet *returned*.
*
* cancel walks this list and sets all operations to canceled,
* calling the driver callbck if neccessary. This goes for ops
* that are finsihed and currently in the users callback. However
* this causes no problem because the cancled flag will not be looked
* at again, and the no driver will be registered for such csllbacks.
*/
/********************************************************************
* data structure macros
*******************************************************************/
#define GlobusXIOHandleSetup(h, a) \
do \
{ \
globus_i_xio_handle_t * _h; \
globus_i_xio_attr_t * _a; \
\
_h = (h); \
_a = (a); \
\
if(_a != NULL) \
{ \
_h->open_timeout_cb = _a->open_timeout_cb; \
GlobusTimeReltimeCopy(_h->open_timeout_period, \
_a->open_timeout_period); \
_h->read_timeout_cb = _a->read_timeout_cb; \
GlobusTimeReltimeCopy(_h->read_timeout_period, \
_a->read_timeout_period); \
_h->write_timeout_cb = _a->write_timeout_cb; \
GlobusTimeReltimeCopy(_h->write_timeout_period, \
_a->write_timeout_period); \
_h->close_timeout_cb = _a->close_timeout_cb; \
GlobusTimeReltimeCopy(_h->close_timeout_period, \
_a->close_timeout_period); \
_h->timeout_arg = _a->timeout_arg; \
} \
} while(0)
#define GlobusLXIOActiveTest() \
if(!globus_l_xio_active) return GlobusXIOErrorNotActivated()
/*
* module activation
*/
#include "version.h"
#include "globus_i_xio.h"
#include "globus_xio.h"
char * globus_i_xio_handle_state_name_table[] =
{
"GLOBUS_XIO_HANDLE_STATE_NONE",
"GLOBUS_XIO_HANDLE_STATE_CLIENT",
"GLOBUS_XIO_HANDLE_STATE_ACCEPTED",
"GLOBUS_XIO_HANDLE_STATE_OPENING",
"GLOBUS_XIO_HANDLE_STATE_OPENING_FAILED",
"GLOBUS_XIO_HANDLE_STATE_OPENING_AND_CLOSING",
"GLOBUS_XIO_HANDLE_STATE_OPEN",
"GLOBUS_XIO_HANDLE_STATE_OPEN_FAILED",
"GLOBUS_XIO_HANDLE_STATE_CLOSING",
"GLOBUS_XIO_HANDLE_STATE_CLOSED",
};
char * globus_i_xio_op_state_name_table[] =
{
"GLOBUS_XIO_OP_STATE_NONE",
"GLOBUS_XIO_OP_STATE_OPERATING",
"GLOBUS_XIO_OP_STATE_TIMEOUT_PENDING",
"GLOBUS_XIO_OP_STATE_FINISH_WAITING",
"GLOBUS_XIO_OP_STATE_FINISHED",
};
char * globus_i_xio_context_state_name_table[] =
{
"GLOBUS_XIO_CONTEXT_STATE_NONE",
"GLOBUS_XIO_CONTEXT_STATE_OPENING",
"GLOBUS_XIO_CONTEXT_STATE_OPEN",
"GLOBUS_XIO_CONTEXT_STATE_OPEN_FAILED",
"GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED",
"GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED",
"GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED_AND_CLOSING",
"GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED_AND_CLOSING",
"GLOBUS_XIO_CONTEXT_STATE_CLOSING",
"GLOBUS_XIO_CONTEXT_STATE_OPENING_AND_CLOSING",
"GLOBUS_XIO_CONTEXT_STATE_CLOSED",
};
/*
* globus_l_xio_prt_ent_s, globus_l_xio_parsed_driver_s, xio_l_scheme,
* and xio_l_scheme_drl_tbl are used in association with the
* globus_xio_handle_create_from_url function.
*
* globus_l_xio_handle_create_from_url_init and
* globus_l_xio_handle_create_from_url_cleanup are used to initialize the
* driver hash table and free its resources, respectively.
* globus_l_xio_handle_create_from_url_drv_unload is used to perform
* the unloads and frees.
*/
#define XIO_MAX_DRIVER_SIZE 16
typedef struct globus_l_xio_prt_ent_s
{
char * prt_name;
char * driver_list[XIO_MAX_DRIVER_SIZE];
} globus_l_xio_prt_ent_t;
typedef struct globus_l_xio_parsed_driver_s
{
globus_xio_driver_t driver;
globus_result_t res;
char * driver_name;
} globus_l_xio_parsed_driver_t;
static globus_l_xio_prt_ent_t xio_l_scheme[] =
{
{"http", {"tcp", "http"}},
{"https", {"tcp", "http", "gsi"}},
{"tcp", {"tcp"}},
{"tcps", {"tcp", "gsi"}},
{"file", {"file"}},
{NULL}
};
static globus_hashtable_t xio_l_scheme_drv_tbl;
void
globus_l_xio_handle_create_from_url_init();
void
globus_l_xio_handle_create_from_url_cleanup();
void
globus_l_xio_handle_create_from_url_drv_unload(
void * datum);
globus_i_xio_timer_t globus_i_xio_timeout_timer;
globus_list_t * globus_i_xio_outstanding_handles_list;
globus_mutex_t globus_i_xio_mutex;
globus_cond_t globus_i_xio_cond;
static globus_bool_t globus_l_xio_active = GLOBUS_FALSE;
GlobusDebugDefine(GLOBUS_XIO);
static globus_result_t
globus_l_xio_register_close(
globus_i_xio_op_t * op);
static globus_result_t
globus_l_xio_handle_cancel_operations(
globus_i_xio_handle_t * xio_handle,
int mask);
static globus_bool_t
globus_l_xio_timeout_callback(
void * user_arg);
static void
globus_l_xio_open_close_callback(
globus_i_xio_op_t * op,
globus_result_t result,
void * user_arg);
void
globus_i_xio_monitor_init(
globus_i_xio_monitor_t * monitor)
{
monitor->count = 0;
}
void
globus_i_xio_monitor_destroy(
globus_i_xio_monitor_t * monitor)
{
}
static
globus_bool_t
globus_l_xio_handle_timeout_always(
globus_xio_handle_t handle,
globus_xio_operation_type_t type,
void * user_arg)
{
return GLOBUS_TRUE;
}
void
globus_l_xio_oneshot_wrapper_cb(
void * user_arg)
{
globus_i_xio_space_info_t * space_info;
globus_i_xio_handle_t * handle;
globus_result_t res;
space_info = (globus_i_xio_space_info_t *) user_arg;
handle = space_info->handle;
if(space_info->unregister)
{
/* remove my reference to the handle */
res = globus_callback_unregister(space_info->ch, NULL, NULL, NULL);
if(res != GLOBUS_SUCCESS)
{
globus_panic(GLOBUS_XIO_MODULE,res,_XIOSL("failed to unregister oneshot"));
}
globus_mutex_lock(&handle->context->cancel_mutex);
{
globus_list_remove(&handle->cb_list,
globus_list_search(handle->cb_list, space_info));
}
globus_mutex_unlock(&handle->context->cancel_mutex);
}
space_info->func(space_info->user_arg);
globus_free(space_info);
}
static void
globus_l_xio_cancel_data_ops(
globus_i_xio_handle_t * handle)
{
globus_list_t * list;
globus_i_xio_op_t * tmp_op;
GlobusXIOName(globus_l_xio_cancel_data_ops);
GlobusXIODebugInternalEnter();
for(list = handle->read_op_list;
!globus_list_empty(list);
list = globus_list_rest(list))
{
tmp_op = (globus_i_xio_op_t *) globus_list_first(list);
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] : canceling read op @ 0x%x\n"),
_xio_name, tmp_op));
globus_i_xio_operation_cancel(tmp_op, -1);
}
for(list = handle->write_op_list;
!globus_list_empty(list);
list = globus_list_rest(list))
{
tmp_op = (globus_i_xio_op_t *) globus_list_first(list);
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] : canceling write op @ 0x%x\n"),
_xio_name, tmp_op));
globus_i_xio_operation_cancel(tmp_op, -1);
}
GlobusXIODebugInternalExit();
}
void
globus_l_xio_open_close_callback_kickout(
void * user_arg);
static
void
globus_l_xio_handle_unopened_close_callback(
void * user_arg)
{
globus_i_xio_op_t * op;
globus_i_xio_handle_t * handle;
GlobusXIOName(globus_l_xio_handle_unopened_close_callback);
GlobusXIODebugInternalEnter();
op = (globus_i_xio_op_t *) user_arg;
handle = op->_op_handle;
globus_mutex_lock(&handle->context->mutex);
GlobusXIOHandleStateChange(handle, GLOBUS_XIO_HANDLE_STATE_CLOSING);
globus_mutex_unlock(&handle->context->mutex);
globus_l_xio_open_close_callback_kickout(op);
GlobusXIODebugInternalExit();
}
static
globus_result_t
globus_l_xio_handle_pre_close(
globus_i_xio_handle_t * handle,
globus_xio_attr_t attr,
globus_xio_callback_t cb,
void * user_arg,
globus_bool_t blocking)
{
void * driver_attr;
int ctr;
globus_bool_t destroy_handle;
globus_i_xio_op_t * op;
globus_result_t res = GLOBUS_SUCCESS;
GlobusXIOName(globus_l_xio_handle_pre_close);
GlobusXIODebugInternalEnter();
GlobusXIOOperationCreate(op, handle->context);
if(op == NULL)
{
res = GlobusXIOErrorMemory("operation");
goto err_param;
}
/*
* set up the operation
*/
op->type = GLOBUS_XIO_OPERATION_TYPE_CLOSE;
op->state = GLOBUS_XIO_OP_STATE_OPERATING;
op->_op_handle = handle;
op->ref = 1;
op->_op_cb = cb;
op->user_arg = user_arg;
op->entry[0].prev_ndx = -1;/*for first pass there is no return*/
op->blocking = blocking;
if(blocking)
{
GlobusXIOCurrentBlockedThread(op->blocked_thread);
}
switch(handle->state)
{
/* the following 3 states catch the case where a handle is closed
* either before opening (accepted or client) or after an open has
* failed (open failed). We don't pass the close down in these cases,
* so we fake a close.
*/
case GLOBUS_XIO_HANDLE_STATE_ACCEPTED:
for(ctr = 0; ctr < handle->context->stack_size; ctr++)
{
if(handle->context->entry[ctr].driver_handle &&
handle->context->entry[ctr].driver->link_destroy_func)
{
handle->context->entry[ctr].driver->link_destroy_func(
handle->context->entry[ctr].driver_handle);
}
}
/* fall through */
case GLOBUS_XIO_HANDLE_STATE_CLIENT:
case GLOBUS_XIO_HANDLE_STATE_OPEN_FAILED:
attr = NULL;
/* pretend we were opening (as this is the pre-opened state) */
GlobusXIOHandleStateChange(handle,
GLOBUS_XIO_HANDLE_STATE_OPENING_AND_CLOSING);
op->state = GLOBUS_XIO_OP_STATE_FINISH_WAITING;
handle->ref++; /* for the opperation */
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[globus_l_xio_handle_pre_close] :: handle ref at %d.\n"), handle->ref));
globus_i_xio_register_oneshot(
handle,
globus_l_xio_handle_unopened_close_callback,
op,
op->blocking ? GLOBUS_CALLBACK_GLOBAL_SPACE : handle->space);
break;
/* if opening, cancel the open */
case GLOBUS_XIO_HANDLE_STATE_OPENING:
globus_assert(handle->open_op != NULL);
if(attr == NULL || !attr->no_cancel)
{
globus_mutex_lock(&handle->context->cancel_mutex);
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] : canceling open op @ 0x%x\n"),
_xio_name, handle->open_op));
/* we delay the pass close until the open callback */
globus_i_xio_operation_cancel(handle->open_op, -1);
/* cancel any data ops */
globus_l_xio_cancel_data_ops(handle);
}
globus_mutex_unlock(&handle->context->cancel_mutex);
}
GlobusXIOHandleStateChange(handle,
GLOBUS_XIO_HANDLE_STATE_OPENING_AND_CLOSING);
break;
case GLOBUS_XIO_HANDLE_STATE_OPENING_FAILED:
GlobusXIOHandleStateChange(handle,
GLOBUS_XIO_HANDLE_STATE_OPENING_AND_CLOSING);
break;
case GLOBUS_XIO_HANDLE_STATE_OPEN:
GlobusXIOHandleStateChange(handle,
GLOBUS_XIO_HANDLE_STATE_CLOSING);
if(attr == NULL || !attr->no_cancel)
{
/* cancel any data ops */
globus_mutex_lock(&handle->context->cancel_mutex);
{
globus_l_xio_cancel_data_ops(handle);
}
globus_mutex_unlock(&handle->context->cancel_mutex);
}
break;
case GLOBUS_XIO_HANDLE_STATE_OPENING_AND_CLOSING:
case GLOBUS_XIO_HANDLE_STATE_CLOSED:
case GLOBUS_XIO_HANDLE_STATE_CLOSING:
res = GlobusXIOErrorInvalidState(handle->state);
goto err;
break;
default:
res = GlobusXIOErrorParameter("handle");
goto err;
break;
}
/* set up op */
for(ctr = 0; ctr < handle->context->stack_size; ctr++)
{
op->entry[ctr].close_attr = NULL;
if(attr != NULL)
{
driver_attr = NULL;
GlobusIXIOAttrGetDS(driver_attr, attr,
handle->context->entry[ctr].driver);
if(driver_attr != NULL)
{
handle->context->entry[ctr].driver->attr_copy_func(
&op->entry[ctr].close_attr, driver_attr);
}
}
}
handle->close_op = op;
GlobusXIODebugInternalExit();
return GLOBUS_SUCCESS;
err:
handle->ref++;
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[globus_l_xio_handle_pre_close] :: handle ref at %d.\n"), handle->ref));
/* so destroy handle can't be true (will be removed in next call) */
op->ref = 0;
globus_i_xio_op_destroy(op, &destroy_handle);
err_param:
GlobusXIODebugInternalExitWithError();
return res;
}
void
globus_i_xio_close_handles(
globus_xio_driver_t driver)
{
globus_list_t * tmp_list;
globus_list_t * c_handles = NULL;
globus_xio_handle_t handle;
globus_i_xio_context_t * context;
globus_xio_server_t server;
globus_i_xio_op_t * dd;
globus_xio_attr_t attr;
globus_bool_t found;
int ctr;
globus_i_xio_monitor_t monitor;
globus_result_t res;
GlobusXIOName(globus_i_xio_close_handles);
GlobusXIODebugInternalEnter();
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("[globus_i_xio_close_handles]: closing driver @0x%x, %s\n"),
driver, driver ? driver->name : "(null)"));
globus_i_xio_monitor_init(&monitor);
/* first destroy all of the dds, as they have references on the handle */
globus_mutex_lock(&globus_i_xio_mutex);
{
tmp_list = globus_list_copy(globus_i_xio_outstanding_dds_list);
while(!globus_list_empty(tmp_list))
{
dd = (globus_i_xio_op_t *) globus_list_remove(&tmp_list, tmp_list);
context = dd->_op_context;
globus_mutex_lock(&context->mutex);
{
found = GLOBUS_FALSE;
for(ctr = 0;
ctr < context->stack_size && !found;
ctr++)
{
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[globus_i_xio_close_handles]: checking dd @0x%x "
"driver @0x%x, %s\n"),
dd,
context->entry[ctr].driver,
context->entry[ctr].driver->name));
if(driver == NULL ||
context->entry[ctr].driver == driver)
{
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("[globus_i_xio_close_handles] : "
"will destroy dd @0x%x\n"), dd));
found = GLOBUS_TRUE;
globus_list_insert(&c_handles, dd);
}
}
}
globus_mutex_unlock(&context->mutex);
}
}
globus_mutex_unlock(&globus_i_xio_mutex);
while(!globus_list_empty(c_handles))
{
dd = (globus_i_xio_op_t *) globus_list_remove(&c_handles, c_handles);
globus_xio_data_descriptor_destroy(dd);
}
globus_mutex_lock(&globus_i_xio_mutex);
{
/* close all open handles */
tmp_list = globus_list_copy(globus_i_xio_outstanding_handles_list);
while(!globus_list_empty(tmp_list))
{
handle = (globus_xio_handle_t)
globus_list_remove(&tmp_list, tmp_list);
globus_assert(handle->context != NULL);
globus_mutex_lock(&handle->context->mutex);
{
/* if it is still in the list i must have no monitor */
globus_assert(handle->sd_monitor == NULL);
found = GLOBUS_FALSE;
for(ctr = 0;
ctr < handle->context->stack_size && !found;
ctr++)
{
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[globus_i_xio_close_handles]: checking handle @0x%x "
"driver @0x%x, %s\n"),
handle,
handle->context->entry[ctr].driver,
handle->context->entry[ctr].driver->name));
/* cancel on al handles */
if(driver == NULL ||
handle->context->entry[ctr].driver == driver)
{
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("[globus_i_xio_close_handles] : "
"will wait on handle @0x%x state=%d\n"),
handle, handle->state));
found = GLOBUS_TRUE;
/* remove from the main list */
globus_list_remove(
&globus_i_xio_outstanding_handles_list,
globus_list_search(
globus_i_xio_outstanding_handles_list, handle));
handle->sd_monitor = &monitor;
monitor.count++;
if(handle->state
!= GLOBUS_XIO_HANDLE_STATE_CLOSING &&
handle->state
!= GLOBUS_XIO_HANDLE_STATE_OPENING_AND_CLOSING &&
handle->state
!= GLOBUS_XIO_HANDLE_STATE_CLOSED)
{
/* i suspect that res will always be true here */
res = globus_l_xio_handle_pre_close(
handle, NULL, NULL, NULL, GLOBUS_TRUE);
if(res != GLOBUS_SUCCESS)
{
/* if pree close fails we will not wait on
this handle */
monitor.count--;
}
else if(handle->state
!= GLOBUS_XIO_HANDLE_STATE_OPENING_AND_CLOSING)
{
globus_list_insert(&c_handles, handle);
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("[globus_i_xio_close_handles] : "
"registersing close on handle @0x%x\n"),
handle));
}
}
}
}
}
globus_mutex_unlock(&handle->context->mutex);
}
/* close all open servers */
tmp_list = globus_list_copy(globus_i_xio_outstanding_servers_list);
while(!globus_list_empty(tmp_list))
{
server = (globus_xio_server_t)
globus_list_remove(&tmp_list, tmp_list);
globus_mutex_lock(&server->mutex);
{
globus_assert(server->sd_monitor == NULL);
found = GLOBUS_FALSE;
for(ctr = 0;
ctr < server->stack_size && !found;
ctr++)
{
if(driver == NULL ||
server->entry[ctr].driver == driver)
{
found = GLOBUS_TRUE;
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("[globus_i_xio_close_handles] : "
"will wait on server @0x%x state=%d\n"),
server, server->state));
globus_list_remove(
&globus_i_xio_outstanding_servers_list,
globus_list_search(
globus_i_xio_outstanding_servers_list, server));
server->sd_monitor = &monitor;
monitor.count++;
if(server->state !=
GLOBUS_XIO_SERVER_STATE_CLOSE_PENDING &&
server->state != GLOBUS_XIO_SERVER_STATE_CLOSING &&
server->state != GLOBUS_XIO_SERVER_STATE_CLOSED)
{
res = globus_i_xio_server_close(
server, NULL, NULL);
if(res != GLOBUS_SUCCESS)
{
monitor.count--;
}
}
}
}
}
globus_mutex_unlock(&server->mutex);
}
/* destroy the internals of all attrs */
tmp_list = globus_list_copy(globus_i_xio_outstanding_attrs_list);
while(!globus_list_empty(tmp_list))
{
attr = (globus_xio_attr_t)
globus_list_remove(&tmp_list, tmp_list);
for(ctr = 0;
ctr < attr->ndx &&
driver != NULL &&
attr->entry[ctr].driver != driver;
ctr++)
{ }
if(ctr < attr->ndx)
{
globus_list_remove(
&globus_i_xio_outstanding_attrs_list,
globus_list_search(
globus_i_xio_outstanding_attrs_list, attr));
for(ctr = 0; ctr < attr->ndx; ctr++)
{
attr->entry[ctr].driver->attr_destroy_func(
attr->entry[ctr].driver_data);
}
attr->unloaded = GLOBUS_TRUE;
}
}
}
globus_mutex_unlock(&globus_i_xio_mutex);
while(!globus_list_empty(c_handles))
{
handle = (globus_xio_handle_t)
globus_list_remove(&c_handles, c_handles);
res = globus_l_xio_register_close(handle->close_op);
if(res != GLOBUS_SUCCESS)
{
globus_mutex_lock(&globus_i_xio_mutex);
{
/* since callbak will not be called we dec here */
monitor.count--;
}
globus_mutex_unlock(&globus_i_xio_mutex);
}
}
globus_mutex_lock(&globus_i_xio_mutex);
{
while(monitor.count != 0)
{
globus_cond_wait(&globus_i_xio_cond, &globus_i_xio_mutex);
}
}
globus_mutex_unlock(&globus_i_xio_mutex);
globus_i_xio_monitor_destroy(&monitor);
GlobusXIODebugInternalExit();
}
void
globus_i_xio_register_oneshot(
globus_i_xio_handle_t * handle,
globus_callback_func_t cb,
void * user_arg,
globus_callback_space_t space)
{
globus_result_t res;
globus_i_xio_space_info_t * space_info;
globus_callback_handle_t * ch = NULL;
GlobusXIOName(globus_i_xio_register_oneshot);
GlobusXIODebugInternalEnter();
if(handle != NULL && space != GLOBUS_CALLBACK_GLOBAL_SPACE)
{
space_info = (globus_i_xio_space_info_t *)
globus_malloc(sizeof(globus_i_xio_space_info_t));
ch = &space_info->ch;
space_info->func = cb;
space_info->unregister = GLOBUS_TRUE;
space_info->handle = handle;
cb = globus_l_xio_oneshot_wrapper_cb;
space_info->user_arg = user_arg;
user_arg = space_info;
globus_mutex_lock(&handle->context->cancel_mutex);
{
globus_list_insert(&handle->cb_list, space_info);
}
globus_mutex_unlock(&handle->context->cancel_mutex);
}
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("registering to space %d, user_arg = 0x%x\n"),
space, user_arg));
res = globus_callback_space_register_oneshot(
ch,
NULL,
cb,
user_arg,
space);
if(res != GLOBUS_SUCCESS)
{
globus_panic(GLOBUS_XIO_MODULE, res, _XIOSL("failed to register oneshot"));
}
GlobusXIODebugInternalExit();
}
static int
globus_l_xio_activate(void)
{
int rc;
GlobusXIOName(globus_l_xio_activate);
GlobusXIODebugInternalEnter();
rc = globus_module_activate(GLOBUS_COMMON_MODULE);
if(rc != 0)
{
return rc;
}
globus_mutex_init(&globus_i_xio_mutex, NULL);
globus_cond_init(&globus_i_xio_cond, NULL);
globus_i_xio_timer_init(&globus_i_xio_timeout_timer);
globus_i_xio_outstanding_handles_list = NULL;
globus_i_xio_outstanding_servers_list = NULL;
globus_i_xio_outstanding_attrs_list = NULL;
globus_i_xio_outstanding_dds_list = NULL;
globus_l_xio_active = GLOBUS_TRUE;
globus_i_xio_load_init();
globus_l_xio_handle_create_from_url_init();
GlobusDebugInit(GLOBUS_XIO,
ERROR WARNING TRACE INTERNAL_TRACE INFO STATE INFO_VERBOSE);
GlobusXIODebugInternalExit();
return GLOBUS_SUCCESS;
}
static int
globus_l_xio_deactivate(void)
{
int rc;
GlobusXIOName(globus_l_xio_deactivate);
GlobusXIODebugInternalEnter();
globus_l_xio_handle_create_from_url_cleanup();
globus_mutex_destroy(&globus_i_xio_mutex);
globus_cond_destroy(&globus_i_xio_cond);
globus_i_xio_timer_destroy(&globus_i_xio_timeout_timer);
globus_i_xio_load_destroy();
globus_l_xio_active = GLOBUS_FALSE;
rc = globus_module_deactivate(GLOBUS_COMMON_MODULE);
GlobusXIODebugInternalExit();
/* GlobusDebugDestroy(GLOBUS_XIO);
*/
return rc;
}
globus_module_descriptor_t globus_i_xio_module =
{
"globus_xio",
globus_l_xio_activate,
globus_l_xio_deactivate,
GLOBUS_NULL,
GLOBUS_NULL,
&local_version
};
void
globus_l_xio_read_write_callback_kickout(
void * user_arg);
/********************************************************************
* Internal functions
*******************************************************************/
/*
* This is called when either an open or a close completes.
*/
static void
globus_l_xio_open_close_callback(
globus_i_xio_op_t * op,
globus_result_t result,
void * user_arg)
{
globus_i_xio_handle_t * handle;
globus_bool_t fire_callback = GLOBUS_TRUE;
GlobusXIOName(globus_l_xio_open_close_callback);
GlobusXIODebugInternalEnter();
handle = op->_op_handle;
globus_mutex_lock(&handle->context->mutex);
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] : op@ 0x%x op->type=%d handle->state=%d\n"),
_xio_name, op, op->type, handle->state));
/* state can be either opening or closing.*/
switch(handle->state)
{
case GLOBUS_XIO_HANDLE_STATE_CLOSING:
globus_assert(op->type == GLOBUS_XIO_OPERATION_TYPE_CLOSE);
handle->close_op = NULL;
break;
case GLOBUS_XIO_HANDLE_STATE_OPENING_AND_CLOSING:
globus_assert(op->type == GLOBUS_XIO_OPERATION_TYPE_OPEN);
break;
case GLOBUS_XIO_HANDLE_STATE_OPENING:
globus_assert(op->type == GLOBUS_XIO_OPERATION_TYPE_OPEN);
if(result != GLOBUS_SUCCESS)
{
GlobusXIOHandleStateChange(handle,
GLOBUS_XIO_HANDLE_STATE_OPENING_FAILED);
}
else
{
GlobusXIOHandleStateChange(handle,
GLOBUS_XIO_HANDLE_STATE_OPEN);
}
break;
case GLOBUS_XIO_HANDLE_STATE_OPENING_FAILED:
case GLOBUS_XIO_HANDLE_STATE_OPEN:
case GLOBUS_XIO_HANDLE_STATE_CLOSED:
default:
globus_assert(0);
}
/* set to finished for the sake of the timeout */
if(op->state == GLOBUS_XIO_OP_STATE_TIMEOUT_PENDING)
{
fire_callback = GLOBUS_FALSE;
}
else
{
fire_callback = GLOBUS_TRUE;
if(op->_op_handle_timeout_cb != NULL)
{
/*
* unregister the cancel
*/
/* if the unregister fails we will get the callback */
if(globus_i_xio_timer_unregister_timeout(
&globus_i_xio_timeout_timer, op))
{
/* at this point we know timeout won't happen */
GlobusXIOOpDec(op);
/* since we have no yet deced for the callbacl this
cannot be zero */
globus_assert(op->ref > 0);
}
}
}
/* remove the operation from the list */
GlobusXIOOpStateChange(op, GLOBUS_XIO_OP_STATE_FINISH_WAITING);
op->cached_obj = GlobusXIOResultToObj(result);
/*
* when at the top don't worry about the cancel
* just act as though we missed it
*/
}
globus_mutex_unlock(&handle->context->mutex);
if(fire_callback)
{
/* we can always call in this stack since Pass macros enforce
registration bariers and callback spaces */
globus_l_xio_open_close_callback_kickout((void *)op);
}
GlobusXIODebugInternalExit();
}
/*
* called by the callback code.
* registerd by finished op when the final (user) callback
* is in a callback space, or if it is under the registraton
* call within the same callstack
*/
void
globus_l_xio_open_close_callback_kickout(
void * user_arg)
{
int ctr;
globus_result_t res;
globus_i_xio_op_t * op;
globus_i_xio_op_t * close_op = NULL;
globus_i_xio_handle_t * handle;
globus_bool_t start_close = GLOBUS_FALSE;
globus_bool_t destroy_handle = GLOBUS_FALSE;
GlobusXIOName(globus_l_xio_open_close_callback_kickout);
GlobusXIODebugInternalEnter();
op = (globus_i_xio_op_t *) user_arg;
handle = op->_op_handle;
/* call the users callback */
if(op->_op_cb != NULL)
{
op->_op_cb(handle, GlobusXIOObjToResult(op->cached_obj), op->user_arg);
}
else if(op->cached_obj != NULL)
{
globus_object_free(op->cached_obj);
}
globus_mutex_lock(&handle->context->mutex);
{
globus_assert(op->state == GLOBUS_XIO_OP_STATE_FINISH_WAITING);
/* this is likely useless, but may help in debugging */
GlobusXIOOpStateChange(op, GLOBUS_XIO_OP_STATE_FINISHED);
/* clean up the links */
if(op->type == GLOBUS_XIO_OPERATION_TYPE_OPEN)
{
for(ctr = 0; ctr < op->stack_size; ctr++)
{
if(op->entry[ctr].link != NULL &&
handle->context->entry[ctr].driver->link_destroy_func !=
NULL)
{
/* ignore result code. user should be more interested in
result from callback */
handle->context->entry[ctr].driver->link_destroy_func(
op->entry[ctr].link);
}
}
}
/* necessary for all states except GLOBUS_XIO_HANDLE_STATE_CLOSED */
handle->open_op = NULL;
switch(handle->state)
{
case GLOBUS_XIO_HANDLE_STATE_OPEN:
globus_assert(op->type == GLOBUS_XIO_OPERATION_TYPE_OPEN);
break;
case GLOBUS_XIO_HANDLE_STATE_OPENING_FAILED:
globus_assert(op->type == GLOBUS_XIO_OPERATION_TYPE_OPEN);
GlobusXIOHandleStateChange(handle,
GLOBUS_XIO_HANDLE_STATE_OPEN_FAILED);
break;
case GLOBUS_XIO_HANDLE_STATE_OPENING_AND_CLOSING:
globus_assert(op->type == GLOBUS_XIO_OPERATION_TYPE_OPEN &&
handle->close_op != NULL);
GlobusXIOHandleStateChange(handle,
GLOBUS_XIO_HANDLE_STATE_CLOSING);
/* start the close */
start_close = GLOBUS_TRUE;
close_op = handle->close_op;
break;
case GLOBUS_XIO_HANDLE_STATE_CLOSING:
/* could be an open op if the user calls close in the
callback */
if(op->type == GLOBUS_XIO_OPERATION_TYPE_CLOSE)
{
GlobusXIOHandleStateChange(handle,
GLOBUS_XIO_HANDLE_STATE_CLOSED);
/* remove handles own reference */
globus_i_xio_handle_dec(handle, &destroy_handle);
/* destroy handle cannot possibly be true yet
the handle stll has the operation reference */
globus_assert(!destroy_handle);
}
break;
/* can enter the closed state if use calls xio_close() in
open callback and the close callback finishes before the
open one returns */
case GLOBUS_XIO_HANDLE_STATE_CLOSED:
break;
case GLOBUS_XIO_HANDLE_STATE_OPENING:
default:
globus_assert(0);
}
/* decrement reference for the operation */
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
}
globus_mutex_unlock(&handle->context->mutex);
/* only gets here if coming from the operning and closing state */
if(start_close)
{
res = globus_l_xio_register_close(close_op);
if(res != GLOBUS_SUCCESS)
{
globus_l_xio_open_close_callback(close_op, res, NULL);
}
globus_assert(!destroy_handle);
}
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
GlobusXIODebugInternalExit();
}
/*
* operation callback for readv and writev operations
* we don't care what the result is, just so it bubbles up to the user
*/
void
globus_i_xio_read_write_callback(
globus_xio_operation_t op,
globus_result_t result,
globus_size_t nbytes,
void * user_arg)
{
globus_i_xio_handle_t * handle;
globus_bool_t fire_operation = GLOBUS_TRUE;
GlobusXIOName(globus_i_xio_read_write_callback);
GlobusXIODebugInternalEnter();
handle = op->_op_handle;
globus_mutex_lock(&handle->context->mutex);
{
globus_assert(handle->state == GLOBUS_XIO_HANDLE_STATE_OPEN ||
handle->state == GLOBUS_XIO_HANDLE_STATE_CLOSING);
/* set to finished for the sake of the timeout */
if(op->state == GLOBUS_XIO_OP_STATE_TIMEOUT_PENDING)
{
fire_operation = GLOBUS_FALSE;
}
else
{
fire_operation = GLOBUS_TRUE;
if(op->_op_handle_timeout_cb != NULL)
{
/*
* unregister the cancel
*/
/* if the unregister fails we will get the callback */
if(globus_i_xio_timer_unregister_timeout(
&globus_i_xio_timeout_timer, op))
{
/* at this point we know timeout won't happen */
GlobusXIOOpDec(op);
}
}
}
GlobusXIOOpStateChange(op, GLOBUS_XIO_OP_STATE_FINISH_WAITING);
if(op->type == GLOBUS_XIO_OPERATION_TYPE_WRITE)
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] : removing write op @ 0x%x\n"),
_xio_name, op));
globus_list_remove(&handle->write_op_list,
globus_list_search(handle->write_op_list, op));
}
else if(op->type == GLOBUS_XIO_OPERATION_TYPE_READ)
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] : removing read op @ 0x%x\n"),
_xio_name, op));
globus_list_remove(&handle->read_op_list,
globus_list_search(handle->read_op_list, op));
}
else
{
globus_assert(0);
}
op->cached_obj = GlobusXIOResultToObj(result);
op->_op_nbytes = nbytes;
}
globus_mutex_unlock(&handle->context->mutex);
if(fire_operation)
{
globus_l_xio_read_write_callback_kickout((void *)op);
}
GlobusXIODebugInternalExit();
}
/*
* called unlocked either by the callback code or in the finsihed op
* state.
*/
void
globus_l_xio_read_write_callback_kickout(
void * user_arg)
{
globus_i_xio_op_t * op;
globus_i_xio_handle_t * handle;
globus_bool_t destroy_handle = GLOBUS_FALSE;
GlobusXIOName(globus_l_xio_read_write_callback_kickout);
GlobusXIODebugInternalEnter();
op = (globus_i_xio_op_t *) user_arg;
handle = op->_op_handle;
if(op->is_user_dd)
{
op->type = GLOBUS_XIO_OPERATION_TYPE_DD;
}
/* call the users callback */
if(op->_op_data_cb != NULL)
{
op->_op_data_cb(
handle,
GlobusXIOObjToResult(op->cached_obj),
op->_op_mem_iovec.iov_base,
op->_op_mem_iovec.iov_len,
op->_op_nbytes,
op,
op->user_arg);
}
else if(op->_op_iovec_cb != NULL)
{
op->_op_iovec_cb(
handle,
GlobusXIOObjToResult(op->cached_obj),
op->_op_iovec,
op->_op_iovec_count,
op->_op_nbytes,
op,
op->user_arg);
}
else if(op->cached_obj != NULL)
{
globus_object_free(op->cached_obj);
}
globus_mutex_lock(&handle->context->mutex);
{
/*
* This is ok in CLOSED state because of will block stuff
*/
globus_assert(handle->state != GLOBUS_XIO_HANDLE_STATE_OPENING);
/* decrement reference for the operation */
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
}
globus_mutex_unlock(&handle->context->mutex);
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
GlobusXIODebugInternalExit();
}
/*
* this starts the cancel processes for the given operation.
*
* the cancel flag is to true. every pass checks this flag and
* if cancel is true the pass fails and the above driver should
* do what it needs to do to cancel the operation. If a driver
* is able to cancel it will call GlobusXIODriverCancelEanble()
* if at the time this function is called the operations cancel
* flag is set to true we register a oneshot for the cancel.
*
* If a cencel occurs while a driver is registered to receive
* cancel notification then the callback is delivered to it.
*
* The framework has little else to do with cancel. The operation
* will come back up via the normal routes with an error.
*/
globus_result_t
globus_i_xio_operation_cancel(
globus_i_xio_op_t * op,
int source_ndx)
{
GlobusXIOName(globus_i_xio_operation_cancel);
GlobusXIODebugInternalEnter();
/* internal function should never be passed NULL */
globus_assert(op != NULL);
if(op->canceled)
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] : op @ 0x%x alread canceled\n"),
_xio_name, op));
goto exit;
}
/* the timeout should only be unregistered if this call is coming
from the user */
if(source_ndx == -1)
{
/*
* if the user oks the cancel then remove the timeout from
* the poller
*/
if(globus_i_xio_timer_unregister_timeout(
&globus_i_xio_timeout_timer, op))
{
GlobusXIOOpDec(op);
}
}
/* since in callback this will always be true */
/*
* set cancel flag
* if a driver has a registered callback it will be called
* if it doesn't the next pass or finished will pick it up
*
* we offset by 2 because source_ndx for user == -1 and top driver == 0
* and we want op->canceled to be non-zero when a cancel is pending.
*/
op->canceled = source_ndx + 2;
/* only cancel it if its not in source's possession
*
* (op->ndx == source_ndx + 1)
*/
if(op->ndx > source_ndx + 1)
{
if(op->cancel_cb != NULL)
{
globus_i_xio_op_entry_t * my_op;
my_op = &op->entry[op->ndx - 1];
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] : op @ 0x%x calling cancel\n"),
_xio_name, op));
my_op->in_register = GLOBUS_TRUE;
op->cancel_cb(op, op->cancel_arg, GLOBUS_XIO_ERROR_CANCELED);
my_op->in_register = GLOBUS_FALSE;
}
}
else
{
/* we set canceled above first to make up for the fact that the
* op->ndx we are reading is not stable. what may happen is that above
* ndx may change to source_ndx + 1 immediately after we read it. this
* would cause us to errorneously 'cancel' this op. This is ok, since
* we are guaranteed to hit the locked section in GlobusIXIOClearCancel
* which will set canceled back to 0 for us
*/
op->canceled = 0;
}
exit:
GlobusXIODebugInternalExit();
return GLOBUS_SUCCESS;
}
static globus_bool_t
globus_l_xio_timeout_callback(
void * user_arg)
{
globus_i_xio_op_t * op;
globus_i_xio_handle_t * handle;
/* rc is definitly set elsewhere but this gets rid of compiler warning
and lets me know that i knew what i was doing */
globus_bool_t rc = GLOBUS_FALSE;
globus_bool_t fire_callback;
globus_bool_t destroy_handle = GLOBUS_FALSE;
globus_bool_t cancel;
globus_bool_t timeout = GLOBUS_FALSE;
/* delayed_cb is in same situation as rc */
globus_callback_func_t delayed_cb = NULL;
globus_callback_space_t space =
GLOBUS_CALLBACK_GLOBAL_SPACE;
GlobusXIOName(globus_l_xio_timeout_callback);
GlobusXIODebugInternalEnter();
op = (globus_i_xio_op_t *) user_arg;
handle = op->_op_handle;
globus_mutex_lock(&handle->context->mutex);
{
switch(op->state)
{
/*
* this case happens when a open operation first pass fails and
* are unable to unregister the timeout and when the operation
* completes but we are unable to unregister the callback.
*/
case GLOBUS_XIO_OP_STATE_FINISHED:
case GLOBUS_XIO_OP_STATE_FINISH_WAITING:
/* decerement the reference for the timeout callback */
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
/* remove it from the timeout list */
rc = GLOBUS_TRUE;
break;
/* this case happens when we actually want to cancel the operation
The timeout code should insure that prograess is false if this
gets called in this state */
case GLOBUS_XIO_OP_STATE_OPERATING:
/* it is up to the timeout callback to set this to true */
rc = GLOBUS_FALSE;
/* cancel the sucker */
globus_assert(op->_op_handle_timeout_cb != NULL);
/* if the driver has blocked the timeout don't call it */
if(!op->block_timeout)
{
timeout = GLOBUS_TRUE;
/* put in canceling state to delay the accept callback */
GlobusXIOOpStateChange(op,
GLOBUS_XIO_OP_STATE_TIMEOUT_PENDING);
}
break;
/* fail on any ohter case */
default:
globus_assert(0);
}
}
globus_mutex_unlock(&handle->context->mutex);
/* if in cancel state, verfiy with user that they want to cancel */
if(timeout)
{
cancel = op->_op_handle_timeout_cb(
handle, op->type, handle->timeout_arg);
}
/* all non time out casses can just return */
else
{
/* wait until outside of lock to free the handle */
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
goto exit;
}
/* if canceling set the res and we will remove this timer event */
if(cancel)
{
rc = GLOBUS_TRUE;
globus_mutex_lock(&handle->context->cancel_mutex);
{
/* Assume all timeouts originate from user */
op->canceled = 1;
if(op->cancel_cb)
{
globus_i_xio_op_entry_t * my_op;
my_op = &op->entry[op->ndx - 1];
my_op->in_register = GLOBUS_TRUE;
op->cancel_cb(op, op->cancel_arg, GLOBUS_XIO_ERROR_TIMEOUT);
my_op->in_register = GLOBUS_FALSE;
}
}
globus_mutex_unlock(&handle->context->cancel_mutex);
}
globus_mutex_lock(&handle->context->mutex);
{
/* if callback has already arriverd set flag to later
call accept callback and set rc to remove timed event */
if(op->state == GLOBUS_XIO_OP_STATE_FINISH_WAITING)
{
fire_callback = GLOBUS_TRUE;
rc = GLOBUS_TRUE;
}
/* if no accept is waiting, set state back to operating */
else
{
fire_callback = GLOBUS_FALSE;
GlobusXIOOpStateChange(op, GLOBUS_XIO_OP_STATE_OPERATING);
}
/* if we are remvoing the timed event */
if(rc)
{
/* decremenet the op reference count and insist that it is
not zero yet */
op->_op_handle_timeout_cb = NULL;
GlobusXIOOpDec(op);
globus_assert(op->ref > 0);
}
/* if the accpet was pending we must call it */
if(fire_callback)
{
switch(op->type)
{
case GLOBUS_XIO_OPERATION_TYPE_OPEN:
case GLOBUS_XIO_OPERATION_TYPE_CLOSE:
delayed_cb = globus_l_xio_open_close_callback_kickout;
break;
case GLOBUS_XIO_OPERATION_TYPE_READ:
case GLOBUS_XIO_OPERATION_TYPE_WRITE:
delayed_cb = globus_l_xio_read_write_callback_kickout;
break;
default:
globus_assert(0);
break;
}
}
}
globus_mutex_unlock(&handle->context->mutex);
if(fire_callback)
{
if(!op->blocking)
{
space = handle->space;
}
if(space != GLOBUS_CALLBACK_GLOBAL_SPACE)
{
/* register a oneshot callback */
globus_i_xio_register_oneshot(
handle,
delayed_cb,
(void *)op,
space);
}
/* in all other cases we can just call callback */
else
{
delayed_cb((void *)op);
}
}
exit:
GlobusXIODebugInternalExit();
return rc;
}
/*
*
*/
globus_result_t
globus_l_xio_register_writev(
globus_i_xio_op_t * op,
int ref)
{
globus_result_t res;
globus_bool_t destroy_handle = GLOBUS_FALSE;
globus_i_xio_handle_t * handle;
GlobusXIOName(globus_l_xio_register_writev);
GlobusXIODebugInternalEnter();
handle = op->_op_handle;
globus_mutex_lock(&handle->context->mutex);
{
handle->ref += ref;
if(handle->state != GLOBUS_XIO_HANDLE_STATE_OPEN)
{
res = GlobusXIOErrorInvalidState(handle->state);
goto bad_state_err;
}
/* register timeout */
if(op->_op_handle->write_timeout_cb != NULL)
{
/* op the operatin reference count for this */
GlobusXIOOpInc(op);
op->_op_handle_timeout_cb = handle->write_timeout_cb;
globus_i_xio_timer_register_timeout(
&globus_i_xio_timeout_timer,
op,
&op->progress,
globus_l_xio_timeout_callback,
&handle->write_timeout_period);
}
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] : inserting write op @ 0x%x\n"),
_xio_name, op));
globus_list_insert(&handle->write_op_list, op);
}
globus_mutex_unlock(&handle->context->mutex);
/* add reference count for the pass. does not need to be done locked
since no one has op until it is passed */
GlobusXIOOpInc(op);
res = globus_xio_driver_pass_write(op, op->_op_iovec, op->_op_iovec_count,
op->_op_wait_for, globus_i_xio_read_write_callback, (void *)NULL);
if(res != GLOBUS_SUCCESS)
{
goto pass_err;
}
globus_mutex_lock(&handle->context->mutex);
{
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
}
globus_mutex_unlock(&handle->context->mutex);
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
GlobusXIODebugInternalExit();
return GLOBUS_SUCCESS;
pass_err:
globus_mutex_lock(&handle->context->mutex);
{
globus_list_remove(&handle->write_op_list,
globus_list_search(handle->write_op_list, op));
GlobusXIOOpDec(op); /* dec for the register */
globus_assert(op->ref > 0);
/* in case timeout unregister fails */
op->type = GLOBUS_XIO_OPERATION_TYPE_FINISHED;
/* if we had a timeout, we need to unregister it */
if(handle->write_timeout_cb != NULL)
{
/* if unregister works remove its reference count */
if(globus_i_xio_timer_unregister_timeout(
&globus_i_xio_timeout_timer, op))
{
GlobusXIOOpDec(op);
globus_assert(op->ref > 0);
}
}
bad_state_err:
/* clean up the operation */
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
/* handle should always have a reference left at this point */
globus_assert(!destroy_handle);
}
}
globus_mutex_unlock(&handle->context->mutex);
GlobusXIODebugInternalExitWithError();
return res;
}
/*
*
*/
globus_result_t
globus_l_xio_register_readv(
globus_i_xio_op_t * op,
int ref)
{
globus_result_t res;
globus_bool_t destroy_handle = GLOBUS_FALSE;
globus_i_xio_handle_t * handle;
GlobusXIOName(globus_l_xio_register_readv);
GlobusXIODebugInternalEnter();
handle = op->_op_handle;
globus_mutex_lock(&handle->context->mutex);
{
handle->ref += ref;
if(handle->state != GLOBUS_XIO_HANDLE_STATE_OPEN)
{
res = GlobusXIOErrorInvalidState(handle->state);
goto bad_state_err;
}
/* this is a bit ugly
handle doesn't maitain this state and Pass asserts for efficieny.
so wee need to check it here to be nice to the user */
if(handle->context->entry[0].state != GLOBUS_XIO_CONTEXT_STATE_OPEN &&
handle->context->entry[0].state !=
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED &&
handle->context->entry[0].state !=
GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED)
{
res = GlobusXIOErrorInvalidState(handle->context->entry[0].state);
goto bad_state_err;
}
/* register timeout */
if(handle->read_timeout_cb != NULL)
{
/* op the operatin reference count for this */
GlobusXIOOpInc(op);
op->_op_handle_timeout_cb = handle->read_timeout_cb;
globus_i_xio_timer_register_timeout(
&globus_i_xio_timeout_timer,
op,
&op->progress,
globus_l_xio_timeout_callback,
&handle->read_timeout_period);
}
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] : inserting read op @ 0x%x\n"),
_xio_name, op));
globus_list_insert(&handle->read_op_list, op);
}
globus_mutex_unlock(&handle->context->mutex);
/* add reference count for the pass. does not need to be done locked
since no one has op until it is passed */
GlobusXIOOpInc(op);
res = globus_xio_driver_pass_read(op, op->_op_iovec, op->_op_iovec_count,
op->_op_wait_for, globus_i_xio_read_write_callback, (void *)NULL);
if(res != GLOBUS_SUCCESS)
{
goto register_err;
}
globus_mutex_lock(&handle->context->mutex);
{
GlobusXIOOpDec(op); /* remove the pass reference */
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
}
globus_mutex_unlock(&handle->context->mutex);
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
GlobusXIODebugInternalExit();
return GLOBUS_SUCCESS;
register_err:
globus_mutex_lock(&handle->context->mutex);
{
globus_list_remove(&handle->read_op_list,
globus_list_search(handle->read_op_list, op));
GlobusXIOOpDec(op); /* unregister the pass */
globus_assert(op->ref > 0);
/* in case timeout unregister fails */
op->type = GLOBUS_XIO_OPERATION_TYPE_FINISHED;
/* if we had a timeout, we need to unregister it */
if(handle->read_timeout_cb != NULL)
{
/* if unregister works remove its reference count */
if(globus_i_xio_timer_unregister_timeout(
&globus_i_xio_timeout_timer, op))
{
GlobusXIOOpDec(op);
globus_assert(op->ref > 0);
}
}
bad_state_err:
/* clean up the operation */
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
/* handle should always have a reference left at this point */
globus_assert(!destroy_handle);
}
}
globus_mutex_unlock(&handle->context->mutex);
GlobusXIODebugInternalExitWithError();
return res;
}
globus_result_t
globus_l_xio_register_open(
globus_i_xio_op_t * op,
const char * contact_string)
{
globus_bool_t destroy_handle = GLOBUS_FALSE;
globus_i_xio_handle_t * handle;
globus_xio_contact_t contact_info;
globus_result_t res;
int ctr;
GlobusXIOName(globus_l_xio_register_open);
GlobusXIODebugInternalEnter();
res = globus_xio_contact_parse(&contact_info, contact_string);
if(res != GLOBUS_SUCCESS)
{
goto err_contact;
}
handle = op->_op_handle;
/* accepted handles have the link structures stored in the driver_handle
* slot. move them into the op now.
*/
if(handle->state == GLOBUS_XIO_HANDLE_STATE_ACCEPTED)
{
/* stick the link in the new handle's context */
for(ctr = 0; ctr < op->stack_size; ctr++)
{
op->entry[ctr].link =
handle->context->entry[ctr].driver_handle;
handle->context->entry[ctr].driver_handle = NULL;
}
}
handle->state = GLOBUS_XIO_HANDLE_STATE_OPENING;
/* register timeout */
if(handle->open_timeout_cb != NULL)
{
/* op the operatin reference count for this */
GlobusXIOOpInc(op);
op->_op_handle_timeout_cb = handle->open_timeout_cb;
globus_i_xio_timer_register_timeout(
&globus_i_xio_timeout_timer,
op,
&op->progress,
globus_l_xio_timeout_callback,
&handle->open_timeout_period);
}
/* add reference count for the pass. does not need to be done locked
since no one has op until it is passed */
GlobusXIOOpInc(op);
res = globus_xio_driver_pass_open(
op, &contact_info, globus_l_xio_open_close_callback, NULL);
globus_xio_contact_destroy(&contact_info);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
globus_mutex_lock(&handle->context->mutex);
{
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
}
globus_mutex_unlock(&handle->context->mutex);
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
GlobusXIODebugInternalExit();
return GLOBUS_SUCCESS;
/*
* error handling
*/
err:
globus_mutex_lock(&handle->context->mutex);
{
handle->state = GLOBUS_XIO_HANDLE_STATE_OPEN_FAILED;
GlobusXIOOpDec(op); /* dec for the register */
globus_assert(op->ref > 0);
if(globus_i_xio_timer_unregister_timeout(
&globus_i_xio_timeout_timer, op))
{
GlobusXIOOpDec(op);
globus_assert(op->ref > 0);
}
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
/* handle should always have a reference left at this point */
globus_assert(!destroy_handle);
}
}
globus_mutex_unlock(&handle->context->mutex);
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
err_contact:
GlobusXIODebugInternalExitWithError();
return res;
}
static globus_result_t
globus_l_xio_register_close(
globus_i_xio_op_t * op)
{
globus_bool_t destroy_handle = GLOBUS_FALSE;
globus_i_xio_handle_t * handle;
globus_result_t res = GLOBUS_SUCCESS;
GlobusXIOName(globus_l_xio_register_close);
GlobusXIODebugInternalEnter();
handle = op->_op_handle;
globus_mutex_lock(&handle->context->mutex);
{
/* register timeout */
if(handle->close_timeout_cb != NULL)
{
/* op the operatin reference count for this */
GlobusXIOOpInc(op);
op->_op_handle_timeout_cb = handle->close_timeout_cb;
globus_i_xio_timer_register_timeout(
&globus_i_xio_timeout_timer,
op,
&op->progress,
globus_l_xio_timeout_callback,
&handle->close_timeout_period);
}
handle->ref++; /* for the opperation */
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[globus_l_xio_register_close] :: handle ref at %d.\n"), handle->ref));
}
globus_mutex_unlock(&handle->context->mutex);
/* add reference count for the pass. does not need to be done locked
since no one has op until it is passed */
GlobusXIOOpInc(op);
res = globus_xio_driver_pass_close(
op, globus_l_xio_open_close_callback, NULL);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
globus_mutex_lock(&handle->context->mutex);
{
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
}
globus_mutex_unlock(&handle->context->mutex);
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
GlobusXIODebugInternalExit();
return GLOBUS_SUCCESS;
err:
globus_mutex_lock(&handle->context->mutex);
{
/* the handle is closed since we will return a failure */
handle->state = GLOBUS_XIO_HANDLE_STATE_CLOSED;
GlobusXIOOpDec(op); /* dec for the register */
globus_assert(op->ref > 0);
if(globus_i_xio_timer_unregister_timeout(
&globus_i_xio_timeout_timer, op))
{
GlobusXIOOpDec(op);
}
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
/* handle should always have a reference left at this point */
globus_assert(!destroy_handle);
}
globus_i_xio_handle_dec(handle, &destroy_handle);
}
globus_mutex_unlock(&handle->context->mutex);
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
GlobusXIODebugInternalExitWithError();
return res;
}
/*
* cancel the operations
*/
static globus_result_t
globus_l_xio_handle_cancel_operations(
globus_i_xio_handle_t * xio_handle,
int mask)
{
globus_list_t * list;
globus_i_xio_op_t * tmp_op;
GlobusXIOName(globus_l_xio_handle_cancel_operations);
GlobusXIODebugInternalEnter();
globus_mutex_lock(&xio_handle->context->cancel_mutex);
{
if(mask & GLOBUS_XIO_CANCEL_OPEN && xio_handle->open_op != NULL)
{
globus_i_xio_operation_cancel(xio_handle->open_op, -1);
}
if(mask & GLOBUS_XIO_CANCEL_CLOSE && xio_handle->close_op != NULL)
{
globus_i_xio_operation_cancel(xio_handle->close_op, -1);
}
if(mask & GLOBUS_XIO_CANCEL_READ)
{
/* remove all outstanding read ops */
for(list = xio_handle->read_op_list;
!globus_list_empty(list);
list = globus_list_rest(list))
{
tmp_op = (globus_i_xio_op_t *) globus_list_first(list);
globus_i_xio_operation_cancel(tmp_op, -1);
}
}
if(mask & GLOBUS_XIO_CANCEL_WRITE)
{
for(list = xio_handle->write_op_list;
!globus_list_empty(list);
list = globus_list_rest(list))
{
tmp_op = (globus_i_xio_op_t *) globus_list_first(list);
globus_i_xio_operation_cancel(tmp_op, -1);
}
}
}
globus_mutex_unlock(&xio_handle->context->cancel_mutex);
GlobusXIODebugInternalExit();
return GLOBUS_SUCCESS;
}
/********************************************************************
* API functions
* -------------
*******************************************************************/
globus_result_t
globus_xio_handle_create(
globus_xio_handle_t * handle,
globus_xio_stack_t stack)
{
globus_i_xio_handle_t * ihandle;
globus_i_xio_context_t * context;
int stack_size;
int ndx;
globus_list_t * list;
globus_result_t res = GLOBUS_SUCCESS;
GlobusXIOName(globus_xio_handle_create);
GlobusXIODebugEnter();
GlobusLXIOActiveTest();
if(handle == NULL)
{
res = GlobusXIOErrorParameter("handle");
goto error_param;
}
*handle = NULL; /* initialze to be nice to user */
if(stack == NULL)
{
res = GlobusXIOErrorParameter("stack");
goto error_param;
}
stack_size = globus_list_size(stack->driver_stack);
if(stack_size == 0)
{
res = GlobusXIOErrorParameter("stack_size");
goto error_param;
}
/* allocate and initialize context */
context = globus_i_xio_context_create(stack_size);
if(context == NULL)
{
res = GlobusXIOErrorMemory("context");
goto error_context;
}
/* allocate and intialize the handle structure */
ihandle = (globus_i_xio_handle_t *)
globus_calloc(1, sizeof(globus_i_xio_handle_t));
if(ihandle == NULL)
{
res = GlobusXIOErrorMemory("ihandle");
goto error_handle;
}
/* initialize the handle */
ihandle->ref = 1; /* itself */
ihandle->context = context;
ihandle->state = GLOBUS_XIO_HANDLE_STATE_CLIENT;
ihandle->space = GLOBUS_CALLBACK_GLOBAL_SPACE;
for(ndx = 0, list = stack->driver_stack;
!globus_list_empty(list);
ndx++, list = globus_list_rest(list))
{
context->entry[ndx].driver = (globus_xio_driver_t)
globus_list_first(list);
}
globus_assert(ndx == stack_size);
globus_mutex_lock(&globus_i_xio_mutex);
{
globus_list_insert(&globus_i_xio_outstanding_handles_list, ihandle);
}
globus_mutex_unlock(&globus_i_xio_mutex);
*handle = ihandle;
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
error_handle:
globus_i_xio_context_destroy(context);
error_context:
error_param:
GlobusXIODebugExitWithError();
return res;
}
/*
* User Open
* ---------
* Check the parameters and state then pass to internal open function.
*/
globus_result_t
globus_xio_register_open(
globus_xio_handle_t handle,
const char * contact_string,
globus_xio_attr_t attr,
globus_xio_callback_t cb,
void * user_arg)
{
void * driver_attr;
globus_i_xio_op_t * op = NULL;
globus_i_xio_context_t * context;
globus_result_t res;
int ctr;
globus_callback_space_t space =
GLOBUS_CALLBACK_GLOBAL_SPACE;
GlobusXIOName(globus_xio_register_open);
GlobusXIODebugEnter();
GlobusLXIOActiveTest();
if(handle == NULL)
{
res = GlobusXIOErrorParameter("handle");
goto err;
}
if(handle->state != GLOBUS_XIO_HANDLE_STATE_CLIENT &&
handle->state != GLOBUS_XIO_HANDLE_STATE_ACCEPTED)
{
res = GlobusXIOErrorInvalidState(handle->state);
goto err;
}
context = handle->context;
GlobusXIOOperationCreate(op, context);
if(op == NULL)
{
res = GlobusXIOErrorMemory("operation");
goto err;
}
GlobusXIOHandleSetup(handle, attr);
/* all memory has been allocated, now set up the different structures */
/*
* set up the operation
*/
op->type = GLOBUS_XIO_OPERATION_TYPE_OPEN;
op->state = GLOBUS_XIO_OP_STATE_OPERATING;
op->_op_handle = handle;
op->ref = 1;
op->ndx = 0;
op->_op_cb = cb;
op->user_arg = user_arg;
op->entry[0].prev_ndx = -1; /* for first pass there is no return */
handle->ref++; /* for operation */
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[globus_xio_register_open] :: handle ref at %d.\n"), handle->ref));
handle->open_op = op;
if(attr != NULL)
{
op->user_open_cred = attr->user_open_cred;
op->user_open_sbj = globus_libc_strdup(attr->user_open_sbj);
op->user_open_username = globus_libc_strdup(attr->user_open_username);
op->user_open_pw = globus_libc_strdup(attr->user_open_pw);
space = attr->space;
/* set entries in structures */
for(ctr = 0; ctr < context->stack_size; ctr++)
{
op->entry[ctr].open_attr = NULL;
GlobusIXIOAttrGetDS(
driver_attr, attr, context->entry[ctr].driver);
if(driver_attr != NULL)
{
context->entry[ctr].driver->attr_copy_func(
&op->entry[ctr].open_attr, driver_attr);
}
}
}
handle->space = space;
globus_callback_space_reference(space);
res = globus_l_xio_register_open(op, contact_string);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
/*
* error handling
*/
err:
GlobusXIODebugExitWithError();
return res;
}
/*
* User Read
* ---------
* Check the parameters and state
* If everything is ok create and setup the operation structure
* fake the iovec structure with the dummy iovec in the operation struct
* Then pass to the internal readv function
*/
globus_result_t
globus_xio_register_read(
globus_xio_handle_t handle,
globus_byte_t * buffer,
globus_size_t buffer_length,
globus_size_t waitforbytes,
globus_xio_data_descriptor_t data_desc,
globus_xio_data_callback_t cb,
void * user_arg)
{
globus_i_xio_op_t * op;
globus_result_t res;
int ref = 0;
GlobusXIOName(globus_xio_register_read);
GlobusXIODebugEnter();
GlobusLXIOActiveTest();
/* error echecking */
if(handle == NULL)
{
return GlobusXIOErrorParameter("handle");
}
if(buffer == NULL)
{
return GlobusXIOErrorParameter("buffer");
}
op = data_desc;
if(op == NULL)
{
GlobusXIOOperationCreate(op, handle->context);
if(op == NULL)
{
res = GlobusXIOErrorMemory("operation");
goto exit;
}
ref = 1;
op->ref = 0;
}
/* set up the operation */
op->type = GLOBUS_XIO_OPERATION_TYPE_READ;
op->state = GLOBUS_XIO_OP_STATE_OPERATING;
op->_op_handle = handle;
GlobusXIOOpInc(op);
op->_op_context = handle->context;
op->_op_data_cb = cb;
op->_op_iovec_cb = NULL;
op->_op_mem_iovec.iov_base = buffer;
op->_op_mem_iovec.iov_len = buffer_length;
op->_op_iovec_count = 1;
op->_op_iovec = &op->_op_mem_iovec;
op->_op_wait_for = waitforbytes;
op->user_arg = user_arg;
op->entry[0].prev_ndx = -1;
res = globus_l_xio_register_readv(op, ref);
if(res != GLOBUS_SUCCESS)
{
goto exit;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
exit:
GlobusXIODebugExitWithError();
return res;
}
/*
* User Readv
* ----------
* Check the parameters and state
* If everything is ok create and setup the operation structure
* Then pass to the internal readv function
*/
globus_result_t
globus_xio_register_readv(
globus_xio_handle_t handle,
globus_xio_iovec_t * iovec,
int iovec_count,
globus_size_t waitforbytes,
globus_xio_data_descriptor_t data_desc,
globus_xio_iovec_callback_t cb,
void * user_arg)
{
globus_result_t res = GLOBUS_SUCCESS;
globus_i_xio_op_t * op;
int ref = 0;
GlobusXIOName(globus_xio_register_readv);
GlobusXIODebugEnter();
GlobusLXIOActiveTest();
/* error echecking */
if(handle == NULL)
{
return GlobusXIOErrorParameter("handle");
}
if(iovec == NULL)
{
return GlobusXIOErrorParameter("iovec");
}
if(iovec_count <= 0)
{
return GlobusXIOErrorParameter("iovec_count");
}
op = data_desc;
if(op == NULL)
{
GlobusXIOOperationCreate(op, handle->context);
if(op == NULL)
{
res = GlobusXIOErrorMemory("operation");
goto exit;
}
ref = 1;
op->ref = 0;
}
/* set up the operation */
op->type = GLOBUS_XIO_OPERATION_TYPE_READ;
op->state = GLOBUS_XIO_OP_STATE_OPERATING;
op->_op_handle = handle;
op->_op_context = handle->context;
GlobusXIOOpInc(op);
op->_op_data_cb = NULL;
op->_op_iovec_cb = cb;
op->_op_iovec = iovec;
op->_op_iovec_count = iovec_count;
op->_op_wait_for = waitforbytes;
op->user_arg = user_arg;
op->entry[0].prev_ndx = -1;
res = globus_l_xio_register_readv(op, ref);
if(res != GLOBUS_SUCCESS)
{
goto exit;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
exit:
GlobusXIODebugExitWithError();
return res;
}
/*
* User Write
* ----------
* Check the parameters and state
* If everything is ok create and setup the operation structure
* fake the iocev structure with the dummy iovec in the operation struct
* Then pass to the internal writev function
*/
globus_result_t
globus_xio_register_write(
globus_xio_handle_t user_handle,
globus_byte_t * buffer,
globus_size_t buffer_length,
globus_size_t waitforbytes,
globus_xio_data_descriptor_t data_desc,
globus_xio_data_callback_t cb,
void * user_arg)
{
globus_i_xio_op_t * op;
globus_result_t res;
globus_i_xio_handle_t * handle;
int ref = 0;
GlobusXIOName(globus_xio_register_write);
GlobusXIODebugEnter();
GlobusLXIOActiveTest();
handle = user_handle;
/* error echecking */
if(handle == NULL)
{
return GlobusXIOErrorParameter("handle");
}
if(buffer == NULL)
{
return GlobusXIOErrorParameter("buffer");
}
op = data_desc;
if(op == NULL)
{
GlobusXIOOperationCreate(op, handle->context);
if(op == NULL)
{
res = GlobusXIOErrorMemory("operation");
goto exit;
}
ref = 1;
op->ref = 0;
}
/* set up the operation */
op->type = GLOBUS_XIO_OPERATION_TYPE_WRITE;
op->state = GLOBUS_XIO_OP_STATE_OPERATING;
GlobusXIOOpInc(op);
op->entry[0].prev_ndx = -1;
op->_op_handle = handle;
op->_op_context = handle->context;
op->_op_data_cb = cb;
op->_op_iovec_cb = NULL;
op->_op_mem_iovec.iov_base = buffer;
op->_op_mem_iovec.iov_len = buffer_length;
op->_op_iovec_count = 1;
op->_op_iovec = &op->_op_mem_iovec;
op->_op_wait_for = waitforbytes;
op->user_arg = user_arg;
res = globus_l_xio_register_writev(op, ref);
if(res != GLOBUS_SUCCESS)
{
goto exit;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
exit:
GlobusXIODebugExitWithError();
return res;
}
/*
* User Writev
* -----------
* Check the parameters and state
* If everything is ok create and setup the operation structure
* Then pass to the internal writev function
*/
globus_result_t
globus_xio_register_writev(
globus_xio_handle_t user_handle,
globus_xio_iovec_t * iovec,
int iovec_count,
globus_size_t waitforbytes,
globus_xio_data_descriptor_t data_desc,
globus_xio_iovec_callback_t cb,
void * user_arg)
{
globus_result_t res = GLOBUS_SUCCESS;
globus_i_xio_op_t * op;
globus_i_xio_handle_t * handle;
int ref = 0;
GlobusXIOName(globus_xio_register_writev);
GlobusXIODebugEnter();
GlobusLXIOActiveTest();
handle = (globus_i_xio_handle_t *) user_handle;
/* error echecking */
if(handle == NULL)
{
return GlobusXIOErrorParameter("handle");
}
if(iovec == NULL)
{
return GlobusXIOErrorParameter("iovec");
}
if(iovec_count <= 0)
{
return GlobusXIOErrorParameter("iovec_count");
}
op = data_desc;
if(op == NULL)
{
GlobusXIOOperationCreate(op, handle->context);
if(op == NULL)
{
res = GlobusXIOErrorMemory("operation");
goto exit;
}
ref = 1;
op->ref = 0;
}
/* set up the operation */
op->type = GLOBUS_XIO_OPERATION_TYPE_WRITE;
op->state = GLOBUS_XIO_OP_STATE_OPERATING;
op->entry[0].prev_ndx = -1;
GlobusXIOOpInc(op);
op->_op_handle = handle;
op->_op_context = handle->context;
op->_op_data_cb = NULL;
op->_op_iovec_cb = cb;
op->_op_iovec = iovec;
op->_op_iovec_count = iovec_count;
op->_op_wait_for = waitforbytes;
op->user_arg = user_arg;
res = globus_l_xio_register_writev(op, ref);
if(res != GLOBUS_SUCCESS)
{
goto exit;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
exit:
GlobusXIODebugExitWithError();
return res;
}
/*
* User Close
* ----------
* Check the parameters and state then pass to internal function.
*/
globus_result_t
globus_xio_register_close(
globus_xio_handle_t handle,
globus_xio_attr_t attr,
globus_xio_callback_t cb,
void * user_arg)
{
globus_result_t res;
/* initialize to remove warn, but not needed */
globus_i_xio_op_t * op = NULL;
globus_bool_t pass = GLOBUS_TRUE;
GlobusXIOName(globus_xio_register_close);
GlobusXIODebugEnter();
GlobusLXIOActiveTest();
/* error echecking */
if(handle == NULL)
{
return GlobusXIOErrorParameter("handle");
}
globus_mutex_lock(&handle->context->mutex);
{
if(handle->sd_monitor != NULL)
{
res = GlobusXIOErrorUnloaded();
}
else
{
res = globus_l_xio_handle_pre_close(
handle, attr, cb, user_arg, GLOBUS_FALSE);
op = handle->close_op;
if(handle->state == GLOBUS_XIO_HANDLE_STATE_OPENING_AND_CLOSING)
{
pass = GLOBUS_FALSE;
}
}
}
globus_mutex_unlock(&handle->context->mutex);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
if(pass)
{
res = globus_l_xio_register_close(op);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
/*
* cancel outstanding operations.
*
* In the furture the attr will control what operations get canceled.
* For now all are canceled.
*/
globus_result_t
globus_xio_handle_cancel_operations(
globus_xio_handle_t handle,
int mask)
{
globus_i_xio_handle_t * xio_handle;
globus_result_t res;
GlobusXIOName(globus_xio_handle_cancel_operations);
GlobusXIODebugEnter();
GlobusLXIOActiveTest();
/* error echecking */
if(handle == NULL)
{
return GlobusXIOErrorParameter("handle");
}
xio_handle = handle;
globus_mutex_lock(&xio_handle->context->mutex);
{
/* if closed there is nothing to cancel */
if(xio_handle->state == GLOBUS_XIO_HANDLE_STATE_CLOSED)
{
res = GlobusXIOErrorInvalidState(xio_handle->state);
}
else
{
res = globus_l_xio_handle_cancel_operations(
xio_handle,
mask);
}
}
globus_mutex_unlock(&xio_handle->context->mutex);
GlobusXIODebugExit();
return res;
}
globus_result_t
globus_xio_handle_cntl(
globus_xio_handle_t handle,
globus_xio_driver_t driver,
int cmd,
...)
{
globus_result_t res = GLOBUS_SUCCESS;
va_list ap;
globus_i_xio_context_t * context;
globus_xio_timeout_callback_t timeout_cb;
globus_reltime_t * delay_time;
GlobusXIOName(globus_xio_handle_cntl);
GlobusXIODebugEnter();
GlobusLXIOActiveTest();
if(handle == NULL)
{
return GlobusXIOErrorParameter("handle");
}
context = handle->context;
if(context == NULL)
{
return GlobusXIOErrorParameter("handle");
}
va_start(ap, cmd);
if(driver != NULL)
{
res = globus_i_xio_driver_handle_cntl(context, 0, driver, cmd, ap);
}
else
{
globus_mutex_lock(&context->mutex);
{
/* do general settings */
switch(cmd)
{
case GLOBUS_XIO_ATTR_SET_TIMEOUT_ALL:
timeout_cb = va_arg(ap, globus_xio_timeout_callback_t);
delay_time = va_arg(ap, globus_reltime_t *);
handle->timeout_arg = va_arg(ap, void *);
if(timeout_cb == NULL)
{
timeout_cb = globus_l_xio_handle_timeout_always;
}
handle->open_timeout_cb = timeout_cb;
handle->close_timeout_cb = timeout_cb;
handle->read_timeout_cb = timeout_cb;
handle->write_timeout_cb = timeout_cb;
GlobusTimeReltimeCopy(
handle->open_timeout_period, *delay_time);
GlobusTimeReltimeCopy(
handle->close_timeout_period, *delay_time);
GlobusTimeReltimeCopy(
handle->read_timeout_period, *delay_time);
GlobusTimeReltimeCopy(
handle->write_timeout_period, *delay_time);
break;
case GLOBUS_XIO_ATTR_SET_TIMEOUT_OPEN:
timeout_cb = va_arg(ap, globus_xio_timeout_callback_t);
delay_time = va_arg(ap, globus_reltime_t *);
handle->timeout_arg = va_arg(ap, void *);
if(timeout_cb == NULL)
{
timeout_cb = globus_l_xio_handle_timeout_always;
}
handle->open_timeout_cb = timeout_cb;
GlobusTimeReltimeCopy(
handle->open_timeout_period, *delay_time);
break;
case GLOBUS_XIO_ATTR_SET_TIMEOUT_CLOSE:
timeout_cb = va_arg(ap, globus_xio_timeout_callback_t);
delay_time = va_arg(ap, globus_reltime_t *);
handle->timeout_arg = va_arg(ap, void *);
if(timeout_cb == NULL)
{
timeout_cb = globus_l_xio_handle_timeout_always;
}
handle->close_timeout_cb = timeout_cb;
GlobusTimeReltimeCopy(
handle->close_timeout_period, *delay_time);
break;
case GLOBUS_XIO_ATTR_SET_TIMEOUT_READ:
timeout_cb = va_arg(ap, globus_xio_timeout_callback_t);
delay_time = va_arg(ap, globus_reltime_t *);
handle->timeout_arg = va_arg(ap, void *);
if(timeout_cb == NULL)
{
timeout_cb = globus_l_xio_handle_timeout_always;
}
handle->read_timeout_cb = timeout_cb;
GlobusTimeReltimeCopy(
handle->read_timeout_period, *delay_time);
break;
case GLOBUS_XIO_ATTR_SET_TIMEOUT_WRITE:
timeout_cb = va_arg(ap, globus_xio_timeout_callback_t);
delay_time = va_arg(ap, globus_reltime_t *);
handle->timeout_arg = va_arg(ap, void *);
if(timeout_cb == NULL)
{
timeout_cb = globus_l_xio_handle_timeout_always;
}
handle->write_timeout_cb = timeout_cb;
GlobusTimeReltimeCopy(
handle->write_timeout_period, *delay_time);
break;
default:
break;
}
}
globus_mutex_unlock(&context->mutex);
}
va_end(ap);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
/************************************************************************
* blocking calls
* --------------
***********************************************************************/
globus_i_xio_blocking_t *
globus_i_xio_blocking_alloc()
{
globus_i_xio_blocking_t * info;
info = (globus_i_xio_blocking_t *)
globus_malloc(sizeof(globus_i_xio_blocking_t));
if(info == NULL)
{
return info;
}
globus_mutex_init(&info->mutex, NULL);
globus_cond_init(&info->cond, NULL);
info->done = GLOBUS_FALSE;
return info;
}
void
globus_i_xio_blocking_destroy(
globus_i_xio_blocking_t * info)
{
globus_mutex_destroy(&info->mutex);
globus_cond_destroy(&info->cond);
globus_free(info);
}
void
globus_l_xio_blocking_cb(
globus_xio_handle_t handle,
globus_result_t result,
void * user_arg)
{
globus_i_xio_blocking_t * info;
info = (globus_i_xio_blocking_t *) user_arg;
globus_mutex_lock(&info->mutex);
{
info->error_obj = GlobusXIOResultToObj(result);
info->done = GLOBUS_TRUE;
globus_cond_signal(&info->cond);
}
globus_mutex_unlock(&info->mutex);
}
void
globus_l_xio_blocking_data_cb(
globus_xio_handle_t handle,
globus_result_t result,
globus_byte_t * buffer,
globus_size_t len,
globus_size_t nbytes,
globus_xio_data_descriptor_t data_desc,
void * user_arg)
{
globus_i_xio_blocking_t * info;
info = (globus_i_xio_blocking_t *) user_arg;
globus_mutex_lock(&info->mutex);
{
info->error_obj = GlobusXIOResultToObj(result);
info->data_desc = data_desc;
info->nbytes = nbytes;
info->done = GLOBUS_TRUE;
globus_cond_signal(&info->cond);
}
globus_mutex_unlock(&info->mutex);
}
void
globus_l_xio_blocking_iov_cb(
globus_xio_handle_t handle,
globus_result_t result,
globus_xio_iovec_t * iovec,
int count,
globus_size_t nbytes,
globus_xio_data_descriptor_t data_desc,
void * user_arg)
{
globus_i_xio_blocking_t * info;
info = (globus_i_xio_blocking_t *) user_arg;
globus_mutex_lock(&info->mutex);
{
info->error_obj = GlobusXIOResultToObj(result);
info->data_desc = data_desc;
info->nbytes = nbytes;
info->done = GLOBUS_TRUE;
globus_cond_signal(&info->cond);
}
globus_mutex_unlock(&info->mutex);
}
globus_result_t
globus_xio_open(
globus_xio_handle_t handle,
const char * contact_string,
globus_xio_attr_t attr)
{
void * driver_attr = NULL;
globus_i_xio_op_t * op;
globus_result_t res = GLOBUS_SUCCESS;
globus_i_xio_context_t * context;
int ctr;
globus_i_xio_blocking_t * info;
globus_callback_space_t space =
GLOBUS_CALLBACK_GLOBAL_SPACE;
GlobusXIOName(globus_xio_open);
GlobusXIODebugEnter();
GlobusLXIOActiveTest();
if(handle == NULL)
{
res = GlobusXIOErrorParameter("handle");
goto param_err;
}
if(handle->state != GLOBUS_XIO_HANDLE_STATE_CLIENT &&
handle->state != GLOBUS_XIO_HANDLE_STATE_ACCEPTED)
{
res = GlobusXIOErrorInvalidState(handle->state);
goto param_err;
}
info = globus_i_xio_blocking_alloc();
if(info == NULL)
{
res = GlobusXIOErrorMemory("internal structure");
goto param_err;
}
context = handle->context;
GlobusXIOOperationCreate(op, context);
if(op == NULL)
{
res = GlobusXIOErrorMemory("operation");
goto op_alloc_error;
}
info->op = op;
GlobusXIOHandleSetup(handle, attr);
/* all memory has been allocated, now set up the different structures */
/*
* set up the operation
*/
op->type = GLOBUS_XIO_OPERATION_TYPE_OPEN;
op->state = GLOBUS_XIO_OP_STATE_OPERATING;
op->_op_handle = handle;
op->ndx = 0;
op->ref = 1;
op->_op_cb = globus_l_xio_blocking_cb;
op->user_arg = info;
op->entry[0].prev_ndx = -1; /* for first pass there is no return */
op->blocking = GLOBUS_TRUE;
GlobusXIOCurrentBlockedThread(op->blocked_thread);
/* initialize the handle */
handle->ref++; /* for operation */
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[globus_xio_open] :: handle ref at %d.\n"), handle->ref));
/* this is set for the cancel */
handle->open_op = op;
if(attr != NULL)
{
op->user_open_cred = attr->user_open_cred;
space = attr->space;
/* set entries in structures */
for(ctr = 0; ctr < context->stack_size; ctr++)
{
op->entry[ctr].open_attr = NULL;
GlobusIXIOAttrGetDS(
driver_attr, attr, context->entry[ctr].driver);
if(driver_attr != NULL)
{
context->entry[ctr].driver->attr_copy_func(
&op->entry[ctr].open_attr, driver_attr);
}
}
}
/* initialize the context */
handle->space = space;
globus_callback_space_reference(space);
res = globus_l_xio_register_open(op, contact_string);
if(res != GLOBUS_SUCCESS)
{
goto register_err;
}
globus_mutex_lock(&info->mutex);
{
while(!info->done)
{
globus_cond_wait(&info->cond, &info->mutex);
}
}
globus_mutex_unlock(&info->mutex);
res = GlobusXIOObjToResult(info->error_obj);
globus_i_xio_blocking_destroy(info);
if(res != GLOBUS_SUCCESS)
{
goto register_err;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
/*
* error handling
*/
op_alloc_error:
globus_i_xio_blocking_destroy(info);
register_err:
param_err:
GlobusXIODebugExitWithError();
return res;
}
/*
* read
*/
globus_result_t
globus_xio_read(
globus_xio_handle_t user_handle,
globus_byte_t * buffer,
globus_size_t buffer_length,
globus_size_t waitforbytes,
globus_size_t * nbytes,
globus_xio_data_descriptor_t data_desc)
{
globus_i_xio_op_t * op;
globus_result_t res;
globus_i_xio_handle_t * handle;
int ref = 0;
globus_i_xio_blocking_t * info;
globus_bool_t destroy_op = GLOBUS_FALSE;
globus_bool_t destroy_handle = GLOBUS_FALSE;
GlobusXIOName(globus_xio_read);
GlobusXIODebugEnter();
GlobusLXIOActiveTest();
handle = user_handle;
/* error echecking */
if(handle == NULL)
{
res = GlobusXIOErrorParameter("handle");
goto param_error;
}
if(buffer == NULL)
{
res = GlobusXIOErrorParameter("buffer");
goto param_error;
}
if(nbytes != NULL)
{
*nbytes = 0;
}
op = data_desc;
if(op == NULL)
{
GlobusXIOOperationCreate(op, handle->context);
if(op == NULL)
{
destroy_op = GLOBUS_TRUE;
res = GlobusXIOErrorMemory("operation");
goto param_error;
}
ref = 1;
op->ref = 0;
}
info = globus_i_xio_blocking_alloc();
if(info == NULL)
{
res = GlobusXIOErrorMemory("internal structure");
goto alloc_error;
}
/* set up the operation */
op->type = GLOBUS_XIO_OPERATION_TYPE_READ;
op->state = GLOBUS_XIO_OP_STATE_OPERATING;
GlobusXIOOpInc(op);
op->entry[0].prev_ndx = -1;
op->_op_handle = handle;
op->_op_context = handle->context;
op->_op_data_cb = globus_l_xio_blocking_data_cb;
op->_op_iovec_cb = NULL;
op->_op_mem_iovec.iov_base = buffer;
op->_op_mem_iovec.iov_len = buffer_length;
op->_op_iovec_count = 1;
op->_op_iovec = &op->_op_mem_iovec;
op->_op_wait_for = waitforbytes;
op->user_arg = info;
op->blocking = GLOBUS_TRUE;
GlobusXIOCurrentBlockedThread(op->blocked_thread);
info->op = op;
res = globus_l_xio_register_readv(op, ref);
if(res != GLOBUS_SUCCESS)
{
goto register_error;
}
globus_mutex_lock(&info->mutex);
{
while(!info->done)
{
globus_cond_wait(&info->cond, &info->mutex);
}
}
globus_mutex_unlock(&info->mutex);
if(nbytes != NULL)
{
*nbytes = info->nbytes;
}
res = GlobusXIOObjToResult(info->error_obj);
globus_i_xio_blocking_destroy(info);
if(res != GLOBUS_SUCCESS)
{
goto alloc_error;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
register_error:
globus_i_xio_blocking_destroy(info);
alloc_error:
/* desroy op */
if(destroy_op)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
param_error:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_readv(
globus_xio_handle_t user_handle,
globus_xio_iovec_t * iovec,
int iovec_count,
globus_size_t waitforbytes,
globus_size_t * nbytes,
globus_xio_data_descriptor_t data_desc)
{
globus_i_xio_op_t * op;
globus_result_t res;
globus_i_xio_handle_t * handle;
int ref = 0;
globus_i_xio_blocking_t * info;
globus_bool_t destroy_op = GLOBUS_FALSE;
globus_bool_t destroy_handle = GLOBUS_FALSE;
GlobusXIOName(globus_xio_readv);
GlobusXIODebugEnter();
GlobusLXIOActiveTest();
handle = user_handle;
/* error echecking */
if(handle == NULL)
{
res = GlobusXIOErrorParameter("handle");
goto param_error;
}
if(iovec == NULL)
{
res = GlobusXIOErrorParameter("iovec");
goto param_error;
}
if(iovec_count <= 0)
{
res = GlobusXIOErrorParameter("iovec_count");
goto param_error;
}
if(nbytes != NULL)
{
*nbytes = 0;
}
op = data_desc;
if(op == NULL)
{
GlobusXIOOperationCreate(op, handle->context);
if(op == NULL)
{
destroy_op = GLOBUS_TRUE;
res = GlobusXIOErrorMemory("operation");
goto param_error;
}
ref = 1;
op->ref = 0;
}
info = globus_i_xio_blocking_alloc();
if(info == NULL)
{
res = GlobusXIOErrorMemory("internal structure");
goto alloc_error;
}
/* set up the operation */
op->type = GLOBUS_XIO_OPERATION_TYPE_READ;
op->state = GLOBUS_XIO_OP_STATE_OPERATING;
GlobusXIOOpInc(op);
op->entry[0].prev_ndx = -1;
op->_op_handle = handle;
op->_op_context = handle->context;
op->_op_data_cb = NULL;
op->_op_iovec_cb = globus_l_xio_blocking_iov_cb;
op->_op_iovec = iovec;
op->_op_iovec_count = iovec_count;
op->_op_wait_for = waitforbytes;
op->user_arg = info;
op->blocking = GLOBUS_TRUE;
GlobusXIOCurrentBlockedThread(op->blocked_thread);
info->op = op;
res = globus_l_xio_register_readv(op, ref);
if(res != GLOBUS_SUCCESS)
{
goto register_error;
}
globus_mutex_lock(&info->mutex);
{
while(!info->done)
{
globus_cond_wait(&info->cond, &info->mutex);
}
}
globus_mutex_unlock(&info->mutex);
if(nbytes != NULL)
{
*nbytes = info->nbytes;
}
res = GlobusXIOObjToResult(info->error_obj);
globus_i_xio_blocking_destroy(info);
if(res != GLOBUS_SUCCESS)
{
goto alloc_error;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
register_error:
globus_i_xio_blocking_destroy(info);
alloc_error:
/* desroy op */
if(destroy_op)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
param_error:
GlobusXIODebugExitWithError();
return res;
}
/*
* writes
*/
globus_result_t
globus_xio_write(
globus_xio_handle_t user_handle,
globus_byte_t * buffer,
globus_size_t buffer_length,
globus_size_t waitforbytes,
globus_size_t * nbytes,
globus_xio_data_descriptor_t data_desc)
{
globus_i_xio_op_t * op;
globus_result_t res;
globus_i_xio_handle_t * handle;
int ref = 0;
globus_i_xio_blocking_t * info;
globus_bool_t destroy_op = GLOBUS_FALSE;
globus_bool_t destroy_handle = GLOBUS_FALSE;
GlobusXIOName(globus_xio_write);
GlobusXIODebugEnter();
GlobusLXIOActiveTest();
handle = user_handle;
/* error echecking */
if(handle == NULL)
{
res = GlobusXIOErrorParameter("handle");
goto param_error;
}
if(buffer == NULL)
{
res = GlobusXIOErrorParameter("buffer");
goto param_error;
}
if(nbytes != NULL)
{
*nbytes = 0;
}
op = data_desc;
if(op == NULL)
{
GlobusXIOOperationCreate(op, handle->context);
if(op == NULL)
{
destroy_op = GLOBUS_TRUE;
res = GlobusXIOErrorMemory("operation");
goto param_error;
}
ref = 1;
op->ref = 0;
}
info = globus_i_xio_blocking_alloc();
if(info == NULL)
{
res = GlobusXIOErrorMemory("internal structure");
goto alloc_error;
}
/* set up the operation */
op->type = GLOBUS_XIO_OPERATION_TYPE_WRITE;
op->state = GLOBUS_XIO_OP_STATE_OPERATING;
GlobusXIOOpInc(op);
op->entry[0].prev_ndx = -1;
op->_op_handle = handle;
op->_op_context = handle->context;
op->_op_data_cb = globus_l_xio_blocking_data_cb;
op->_op_iovec_cb = NULL;
op->_op_mem_iovec.iov_base = buffer;
op->_op_mem_iovec.iov_len = buffer_length;
op->_op_iovec_count = 1;
op->_op_iovec = &op->_op_mem_iovec;
op->_op_wait_for = waitforbytes;
op->user_arg = info;
op->blocking = GLOBUS_TRUE;
GlobusXIOCurrentBlockedThread(op->blocked_thread);
info->op = op;
res = globus_l_xio_register_writev(op, ref);
if(res != GLOBUS_SUCCESS)
{
goto register_error;
}
globus_mutex_lock(&info->mutex);
{
while(!info->done)
{
globus_cond_wait(&info->cond, &info->mutex);
}
}
globus_mutex_unlock(&info->mutex);
if(nbytes != NULL)
{
*nbytes = info->nbytes;
}
res = GlobusXIOObjToResult(info->error_obj);
globus_i_xio_blocking_destroy(info);
if(res != GLOBUS_SUCCESS)
{
goto alloc_error;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
register_error:
globus_i_xio_blocking_destroy(info);
alloc_error:
/* desroy op */
if(destroy_op)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
param_error:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_writev(
globus_xio_handle_t user_handle,
globus_xio_iovec_t * iovec,
int iovec_count,
globus_size_t waitforbytes,
globus_size_t * nbytes,
globus_xio_data_descriptor_t data_desc)
{
globus_bool_t destroy_op = GLOBUS_FALSE;
globus_bool_t destroy_handle = GLOBUS_FALSE;
globus_i_xio_op_t * op;
globus_result_t res;
globus_i_xio_handle_t * handle;
int ref = 0;
globus_i_xio_blocking_t * info;
GlobusXIOName(globus_xio_writev);
GlobusXIODebugEnter();
GlobusLXIOActiveTest();
handle = user_handle;
/* error echecking */
if(handle == NULL)
{
res = GlobusXIOErrorParameter("handle");
goto param_error;
}
if(iovec == NULL)
{
res = GlobusXIOErrorParameter("iovec");
goto param_error;
}
if(iovec_count <= 0)
{
res = GlobusXIOErrorParameter("iovec_count");
goto param_error;
}
if(nbytes != NULL)
{
*nbytes = 0;
}
op = data_desc;
if(op == NULL)
{
GlobusXIOOperationCreate(op, handle->context);
if(op == NULL)
{
destroy_op = GLOBUS_TRUE;
res = GlobusXIOErrorMemory("operation");
goto param_error;
}
ref = 1;
op->ref = 0;
}
info = globus_i_xio_blocking_alloc();
if(info == NULL)
{
res = GlobusXIOErrorMemory("internal structure");
goto alloc_error;
}
/* set up the operation */
op->type = GLOBUS_XIO_OPERATION_TYPE_WRITE;
op->state = GLOBUS_XIO_OP_STATE_OPERATING;
GlobusXIOOpInc(op);
op->entry[0].prev_ndx = -1;
op->_op_handle = handle;
op->_op_context = handle->context;
op->_op_data_cb = NULL;
op->_op_iovec_cb = globus_l_xio_blocking_iov_cb;
op->_op_iovec = iovec;
op->_op_iovec_count = iovec_count;
op->_op_wait_for = waitforbytes;
op->user_arg = info;
op->blocking = GLOBUS_TRUE;
GlobusXIOCurrentBlockedThread(op->blocked_thread);
info->op = op;
res = globus_l_xio_register_writev(op, ref);
if(res != GLOBUS_SUCCESS)
{
goto register_error;
}
globus_mutex_lock(&info->mutex);
{
while(!info->done)
{
globus_cond_wait(&info->cond, &info->mutex);
}
}
globus_mutex_unlock(&info->mutex);
if(nbytes != NULL)
{
*nbytes = info->nbytes;
}
res = GlobusXIOObjToResult(info->error_obj);
globus_i_xio_blocking_destroy(info);
if(res != GLOBUS_SUCCESS)
{
goto alloc_error;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
register_error:
globus_i_xio_blocking_destroy(info);
alloc_error:
/* desroy op */
if(destroy_op)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
param_error:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_close(
globus_xio_handle_t handle,
globus_xio_attr_t attr)
{
globus_result_t res = GLOBUS_SUCCESS;
globus_i_xio_blocking_t * info;
globus_bool_t pass = GLOBUS_TRUE;
globus_bool_t destroy_handle = GLOBUS_FALSE;
int ctr;
GlobusXIOName(globus_xio_close);
GlobusXIODebugEnter();
GlobusLXIOActiveTest();
/* error echecking */
if(handle == NULL)
{
res = GlobusXIOErrorParameter("handle");
goto param_error;
}
info = globus_i_xio_blocking_alloc();
if(info == NULL)
{
res = GlobusXIOErrorMemory("internal structure");
goto alloc_error;
}
globus_mutex_lock(&handle->context->mutex);
{
if(handle->sd_monitor != NULL)
{
res = GlobusXIOErrorUnloaded();
}
else if(handle->state == GLOBUS_XIO_HANDLE_STATE_CLIENT ||
handle->state == GLOBUS_XIO_HANDLE_STATE_ACCEPTED ||
handle->state == GLOBUS_XIO_HANDLE_STATE_OPENING_FAILED ||
handle->state == GLOBUS_XIO_HANDLE_STATE_OPEN_FAILED)
{
/* we avoid the oneshot and blocking call by handling these cases
* now. Since the stack was never successfully opened, we don't
* need to pass close
*/
if(handle->state == GLOBUS_XIO_HANDLE_STATE_ACCEPTED)
{
/* do need to destroy the accepted links, though */
for(ctr = 0; ctr < handle->context->stack_size; ctr++)
{
if(handle->context->entry[ctr].driver_handle &&
handle->context->entry[ctr].driver->link_destroy_func)
{
handle->context->entry[ctr].driver->link_destroy_func(
handle->context->entry[ctr].driver_handle);
}
}
}
GlobusXIOHandleStateChange(handle, GLOBUS_XIO_HANDLE_STATE_CLOSED);
destroy_handle = GLOBUS_TRUE;
pass = GLOBUS_FALSE;
}
else
{
res = globus_l_xio_handle_pre_close(
handle, attr, globus_l_xio_blocking_cb, info, GLOBUS_TRUE);
if(handle->state ==
GLOBUS_XIO_HANDLE_STATE_OPENING_AND_CLOSING)
{
pass = GLOBUS_FALSE;
}
}
}
globus_mutex_unlock(&handle->context->mutex);
if(res != GLOBUS_SUCCESS)
{
goto register_error;
}
if(pass)
{
res = globus_l_xio_register_close(handle->close_op);
if(res != GLOBUS_SUCCESS)
{
goto register_error;
}
}
if(destroy_handle)
{
globus_i_xio_handle_dec(handle, &destroy_handle);
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
}
else
{
globus_mutex_lock(&info->mutex);
{
while(!info->done)
{
globus_cond_wait(&info->cond, &info->mutex);
}
}
globus_mutex_unlock(&info->mutex);
res = GlobusXIOObjToResult(info->error_obj);
}
globus_i_xio_blocking_destroy(info);
if(res != GLOBUS_SUCCESS)
{
goto alloc_error;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
register_error:
globus_i_xio_blocking_destroy(info);
/* desroy op */
alloc_error:
param_error:
GlobusXIODebugExitWithError();
return res;
}
void
globus_l_xio_handle_create_from_url_init()
{
globus_hashtable_init(
&xio_l_scheme_drv_tbl,
256,
globus_hashtable_string_hash,
globus_hashtable_string_keyeq);
}
void
globus_l_xio_handle_create_from_url_cleanup()
{
globus_hashtable_destroy_all(
&xio_l_scheme_drv_tbl,
globus_l_xio_handle_create_from_url_drv_unload);
}
void
globus_l_xio_handle_create_from_url_drv_unload(
void * datum)
{
globus_l_xio_parsed_driver_t * ent;
ent = (globus_l_xio_parsed_driver_t *) datum;
globus_xio_driver_unload(ent->driver);
free(ent);
}
globus_result_t
globus_xio_handle_create_from_url(
globus_xio_handle_t * out_h,
const char * in_scheme,
globus_xio_attr_t attr,
char * param_string)
{
globus_url_t url;
globus_result_t res;
globus_xio_stack_t stack;
int i;
int j;
char * scheme;
globus_l_xio_parsed_driver_t * ent;
globus_list_t * proto_list = NULL;
int list_size;
char * list_string;
char * driver_opts;
int driver_match;
res = globus_url_parse(
in_scheme,
&url);
if(res != GLOBUS_SUCCESS)
{
scheme = strdup(in_scheme);
}
else
{
scheme = strdup(url.scheme);
globus_url_destroy(&url);
}
res = globus_xio_stack_init(
&stack,
NULL);
if(res != GLOBUS_SUCCESS)
{
goto error_stack;
}
for(i = 0; xio_l_scheme[i].prt_name != NULL; i++)
{
if(strcmp(xio_l_scheme[i].prt_name, scheme) == 0)
{
for(j = 0; xio_l_scheme[i].driver_list[j] != NULL; j++)
{
ent = (globus_l_xio_parsed_driver_t * )globus_hashtable_lookup(
&xio_l_scheme_drv_tbl,
(void *)xio_l_scheme[i].driver_list[j]);
if(ent == NULL)
{
ent = (globus_l_xio_parsed_driver_t *)
globus_malloc(sizeof(globus_l_xio_parsed_driver_t));
ent->driver_name = strdup(xio_l_scheme[i].driver_list[j]);
ent->res = globus_xio_driver_load(
xio_l_scheme[i].driver_list[j],
&ent->driver);
globus_hashtable_insert(
&xio_l_scheme_drv_tbl,
(void *)xio_l_scheme[i].driver_list[j],
(void *)ent);
}
globus_assert(ent != NULL);
if(ent->res != GLOBUS_SUCCESS)
{
goto error_lookup;
}
if(param_string != NULL)
{
proto_list = globus_list_from_string(
param_string, ',', NULL);
list_size = globus_list_size(proto_list);
while(list_size > 0)
{
list_string = (char *)globus_list_remove(
&proto_list, proto_list);
driver_opts = strstr(list_string, ":") + 1;
/* check if the driver name matches the param string */
driver_match = strncmp(
list_string,
ent->driver_name,
strlen(ent->driver_name));
if(attr != NULL && driver_opts != NULL &&
driver_match == 0)
{
res = globus_xio_attr_cntl(
attr,
ent->driver,
GLOBUS_XIO_SET_STRING_OPTIONS,
driver_opts);
}
free((void *)list_string);
if(res != GLOBUS_SUCCESS)
{
goto error_attr_cntl;
}
list_size--;
}
}
res = globus_xio_stack_push_driver(
stack, ent->driver);
if(res != GLOBUS_SUCCESS)
{
goto error_push;
}
}
}
}
res = globus_xio_handle_create(out_h, stack);
if(res != GLOBUS_SUCCESS)
{
goto error_destroy_handle;
}
globus_xio_stack_destroy(stack);
free(scheme);
return GLOBUS_SUCCESS;
error_destroy_handle:
error_push:
error_attr_cntl:
if(proto_list != NULL)
{
while(globus_list_size(proto_list) > 0)
{
free(globus_list_remove(&proto_list, proto_list));
}
}
error_lookup:
globus_xio_stack_destroy(stack);
error_stack:
free(scheme);
return res;
}
globus_xio-6.6/PaxHeaders.22691/globus_xio_driver.c 0000644 0000000 0000000 00000000132 14243161125 020427 x ustar 00 0000000 0000000 30 mtime=1653400149.722966433
30 atime=1653401488.451573387
30 ctime=1653403998.747961542
globus_xio-6.6/globus_xio_driver.c 0000664 0001750 0001750 00000216041 14243161125 020573 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "globus_xio.h"
#include "globus_i_xio.h"
static
globus_bool_t
globus_l_xio_server_timeout_always(
globus_xio_server_t server,
globus_xio_operation_type_t type)
{
return GLOBUS_TRUE;
}
static
globus_bool_t
globus_l_xio_timeout_always(
globus_xio_handle_t handle,
globus_xio_operation_type_t type,
void * user_arg)
{
return GLOBUS_TRUE;
}
void
globus_l_xio_op_restarted(
globus_i_xio_op_t * op)
{
globus_bool_t destroy_handle = GLOBUS_FALSE;
globus_i_xio_context_t * context;
globus_i_xio_handle_t * handle;
GlobusXIOName(globus_l_xio_op_restarted);
GlobusXIODebugInternalEnter();
context = op->_op_context;
handle = op->_op_handle;
globus_mutex_lock(&context->mutex);
{
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
}
globus_mutex_unlock(&context->mutex);
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
GlobusXIODebugInternalExit();
}
globus_result_t
globus_i_xio_repass_write(
globus_i_xio_op_t * op)
{
globus_i_xio_op_entry_t * my_op;
globus_i_xio_context_entry_t * next_context;
globus_result_t res;
globus_xio_iovec_t * tmp_iovec;
int iovec_count;
GlobusXIOName(globus_i_xio_repass_write);
GlobusXIODebugInternalEnter();
my_op = &op->entry[op->ndx - 1];
next_context = &op->_op_context->entry[op->ndx - 1];
/* allocate tmp iovec to the bigest it could ever be */
if(my_op->_op_ent_fake_iovec == NULL)
{
my_op->_op_ent_fake_iovec = (globus_xio_iovec_t *)
globus_malloc(sizeof(globus_xio_iovec_t) *
my_op->_op_ent_iovec_count);
}
tmp_iovec = my_op->_op_ent_fake_iovec;
GlobusIXIOUtilTransferAdjustedIovec(
tmp_iovec, iovec_count,
my_op->_op_ent_iovec, my_op->_op_ent_iovec_count,
my_op->_op_ent_nbytes);
/* repass the operation down */
res = next_context->driver->write_func(
next_context->driver_handle,
tmp_iovec,
iovec_count,
op);
GlobusXIODebugInternalExit();
return res;
}
globus_result_t
globus_i_xio_repass_read(
globus_i_xio_op_t * op)
{
globus_i_xio_op_entry_t * my_op;
globus_i_xio_context_entry_t * next_context;
globus_result_t res;
globus_xio_iovec_t * tmp_iovec;
int iovec_count;
GlobusXIOName(globus_i_xio_repass_read);
GlobusXIODebugInternalEnter();
my_op = &op->entry[op->ndx - 1];
next_context = &op->_op_context->entry[op->ndx - 1];
/* allocate tmp iovec to the bigest it could ever be */
if(my_op->_op_ent_fake_iovec == NULL)
{
my_op->_op_ent_fake_iovec = (globus_xio_iovec_t *)
globus_malloc(sizeof(globus_xio_iovec_t) *
my_op->_op_ent_iovec_count);
}
tmp_iovec = my_op->_op_ent_fake_iovec;
GlobusIXIOUtilTransferAdjustedIovec(
tmp_iovec, iovec_count,
my_op->_op_ent_iovec, my_op->_op_ent_iovec_count,
my_op->_op_ent_nbytes);
/* repass the operation down */
res = next_context->driver->read_func(
next_context->driver_handle,
tmp_iovec,
iovec_count,
op);
GlobusXIODebugInternalExit();
return res;
}
void
globus_i_xio_pass_failed(
globus_i_xio_op_t * op,
globus_i_xio_context_entry_t * my_context,
globus_bool_t * close,
globus_bool_t * destroy_handle)
{
GlobusXIOName(globus_i_xio_pass_failed);
GlobusXIODebugInternalEnter();
my_context->outstanding_operations--;
/*there is an off chance that we could need to close here*/
if((my_context->state == GLOBUS_XIO_CONTEXT_STATE_CLOSING ||
my_context->state ==
GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED_AND_CLOSING) &&
my_context->outstanding_operations == 0 &&
!my_context->close_started)
{
globus_assert(my_context->close_op != NULL);
*close = GLOBUS_TRUE;
}
op->ndx = op->entry[op->ndx - 1].prev_ndx;
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, destroy_handle);
}
GlobusXIODebugInternalExit();
}
void
globus_i_xio_handle_destroy(
globus_i_xio_handle_t * handle)
{
globus_bool_t destroy_context = GLOBUS_FALSE;
GlobusXIOName(globus_i_xio_handle_destroy);
GlobusXIODebugInternalEnter();
globus_mutex_lock(&globus_i_xio_mutex);
{
globus_mutex_lock(&handle->context->mutex);
{
handle->context->ref--;
if(handle->context->ref == 0)
{
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("[globus_i_xio_handle_destroy] :: context->ref == 0.\n")));
destroy_context = GLOBUS_TRUE;
}
if(handle->sd_monitor != NULL)
{
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("[globus_i_xio_handle_destroy]"
" :: signalling handle unload.\n")));
handle->sd_monitor->count--;
if(handle->sd_monitor->count == 0)
{
globus_cond_signal(&globus_i_xio_cond);
}
}
else
{
globus_list_remove(&globus_i_xio_outstanding_handles_list,
globus_list_search(
globus_i_xio_outstanding_handles_list, handle));
}
}
globus_mutex_unlock(&handle->context->mutex);
}
globus_mutex_unlock(&globus_i_xio_mutex);
if(destroy_context)
{
globus_i_xio_context_destroy(handle->context);
}
globus_assert(handle->ref == 0);
globus_callback_space_destroy(handle->space);
globus_free(handle);
GlobusXIODebugInternalExit();
}
/*
* called in the context lock
*/
void
globus_i_xio_handle_dec(
globus_i_xio_handle_t * handle,
globus_bool_t * destroy_handle)
{
globus_result_t res;
globus_i_xio_space_info_t * space_info;
GlobusXIOName(globus_i_xio_handle_dec);
GlobusXIODebugInternalEnter();
*destroy_handle = GLOBUS_FALSE;
handle->ref--;
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[globus_i_xio_handle_dec] :: handle ref at %d.\n"), handle->ref));
if(handle->ref == 0)
{
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("[globus_i_xio_handle_dec] :: handle ref at 0.\n")));
globus_assert(handle->state == GLOBUS_XIO_HANDLE_STATE_CLOSED);
*destroy_handle = GLOBUS_TRUE;
/* purge the ch list */
while(!globus_list_empty(handle->cb_list))
{
space_info = (globus_i_xio_space_info_t *)
globus_list_remove(&handle->cb_list, handle->cb_list);
res = globus_callback_unregister(
space_info->ch,
NULL,
NULL,
NULL);
if(res != GLOBUS_SUCCESS)
{
globus_panic(GLOBUS_XIO_MODULE, res, _XIOSL("failed to unregister"));
}
}
}
GlobusXIODebugInternalExit();
}
/*
* called locked
*/
void
globus_i_xio_op_destroy(
globus_i_xio_op_t * op,
globus_bool_t * destroy_handle)
{
globus_i_xio_handle_t * handle;
globus_i_xio_context_t * context;
int ctr;
GlobusXIOName(globus_i_xio_op_destroy);
GlobusXIODebugInternalEnter();
context = op->_op_context;
handle = op->_op_handle;
globus_assert(op->ref == 0);
for(ctr = 0; ctr < op->stack_size; ctr++)
{
if(op->entry[ctr].dd != NULL)
{
op->_op_context->entry[ctr].driver->attr_destroy_func(
op->entry[ctr].dd);
}
if(op->_op_context->entry[ctr].driver->attr_destroy_func != NULL &&
op->entry[ctr].open_attr != NULL)
{
op->_op_context->entry[ctr].driver->attr_destroy_func(
op->entry[ctr].open_attr);
op->entry[ctr].open_attr = NULL;
}
if(op->_op_context->entry[ctr].driver->attr_destroy_func != NULL &&
op->entry[ctr].close_attr != NULL)
{
op->_op_context->entry[ctr].driver->attr_destroy_func(
op->entry[ctr].close_attr);
op->entry[ctr].close_attr = NULL;
}
}
if(op->user_open_sbj)
{
globus_free(op->user_open_sbj);
}
if(op->user_open_username)
{
globus_free(op->user_open_username);
}
if(op->user_open_pw)
{
globus_free(op->user_open_pw);
}
globus_memory_push_node(&context->op_memory, op);
if(handle != NULL)
{
globus_i_xio_handle_dec(handle, destroy_handle);
}
else
{
*destroy_handle = GLOBUS_FALSE;
}
GlobusXIODebugInternalExit();
}
void
globus_i_xio_driver_resume_op(
globus_i_xio_op_t * op)
{
GlobusXIOName(globus_i_xio_driver_resume_op);
GlobusXIODebugInternalEnter();
switch(op->entry[op->ndx - 1].type)
{
case GLOBUS_XIO_OPERATION_TYPE_OPEN:
globus_l_xio_driver_open_op_kickout(op);
break;
case GLOBUS_XIO_OPERATION_TYPE_READ:
globus_l_xio_driver_op_read_kickout(op);
break;
case GLOBUS_XIO_OPERATION_TYPE_WRITE:
globus_l_xio_driver_op_write_kickout(op);
break;
case GLOBUS_XIO_OPERATION_TYPE_CLOSE:
globus_l_xio_driver_op_close_kickout(op);
break;
default:
globus_assert(0 &&
"Unexpected state in globus_i_xio_driver_resume_op");
break;
}
GlobusXIODebugInternalExit();
}
void
globus_i_xio_driver_deliver_op(
globus_i_xio_op_t * op,
int ndx,
globus_xio_operation_type_t deliver_type)
{
GlobusXIOName(globus_i_xio_driver_deliver_op);
GlobusXIODebugInternalEnter();
switch(deliver_type)
{
case GLOBUS_XIO_OPERATION_TYPE_OPEN:
globus_xio_driver_open_delivered(op, ndx, &deliver_type);
break;
case GLOBUS_XIO_OPERATION_TYPE_READ:
globus_xio_driver_read_delivered(op, ndx, &deliver_type);
break;
case GLOBUS_XIO_OPERATION_TYPE_WRITE:
globus_xio_driver_write_delivered(op, ndx, &deliver_type);
break;
default:
globus_assert(0);
break;
}
GlobusXIODebugInternalExit();
}
void
globus_i_xio_will_block_cb(
globus_thread_callback_index_t wb_ndx,
globus_callback_space_t space,
void * user_args)
{
globus_xio_operation_type_t deliver_type;
globus_i_xio_op_t * op;
globus_i_xio_context_t * context;
int ndx;
GlobusXIOName(globus_i_xio_will_block_cb);
GlobusXIODebugInternalEnter();
op = (globus_i_xio_op_t *) user_args;
globus_thread_blocking_callback_disable(&wb_ndx);
context = op->_op_context;
op->restarted = GLOBUS_TRUE;
globus_assert(op->ndx == 0);
ndx = op->ndx;
do
{
globus_mutex_lock(&context->mutex);
{
if(op->entry[ndx].deliver_type != NULL)
{
GlobusXIOOpInc(op);
deliver_type = *op->entry[ndx].deliver_type;
*op->entry[ndx].deliver_type =
GLOBUS_XIO_OPERATION_TYPE_FINISHED;
op->entry[ndx].deliver_type = NULL;
}
else
{
deliver_type = GLOBUS_XIO_OPERATION_TYPE_FINISHED;
}
}
globus_mutex_unlock(&context->mutex);
switch(deliver_type)
{
case GLOBUS_XIO_OPERATION_TYPE_OPEN:
globus_xio_driver_open_delivered(op, ndx, &deliver_type);
break;
case GLOBUS_XIO_OPERATION_TYPE_READ:
globus_xio_driver_read_delivered(op, ndx, &deliver_type);
break;
case GLOBUS_XIO_OPERATION_TYPE_WRITE:
globus_xio_driver_write_delivered(op, ndx, &deliver_type);
break;
/* none happens if a driver finishes without passing*/
case GLOBUS_XIO_OPERATION_TYPE_NONE:
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s:%d] :: type none, exiting\n"), _xio_name, __LINE__));
goto exit;
/* finishe state means the operation was already delivered */
case GLOBUS_XIO_OPERATION_TYPE_FINISHED:
break;
case GLOBUS_XIO_OPERATION_TYPE_CLOSE:
break;
default:
globus_assert(0);
break;
}
ndx = op->entry[ndx].next_ndx;
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s:%d] :: Index = %d\n"), _xio_name, __LINE__, ndx));
}
while(ndx != op->stack_size && ndx != 0);
exit:
GlobusXIODebugInternalExit();
}
void
globus_l_xio_driver_op_write_kickout(
void * user_arg)
{
globus_xio_operation_type_t deliver_type;
int ndx;
int wb_ndx;
globus_i_xio_handle_t * handle;
globus_i_xio_op_entry_t * my_op;
globus_i_xio_op_t * op;
GlobusXIOName(globus_l_xio_driver_op_write_kickout);
GlobusXIODebugInternalEnter();
op = (globus_i_xio_op_t *) user_arg;
my_op = &op->entry[op->ndx - 1];
op->entry[my_op->prev_ndx].next_ndx = op->ndx;
op->ndx = my_op->prev_ndx;
ndx = op->ndx;
handle = op->_op_handle;
GlobusIXIOClearCancel(op);
/*
* before releasing the op back to the user we can safely set this
* outside of a mutex. Once the users callbcak is called the value
* on the local stack may be changed, theus the magic.
*/
deliver_type = my_op->type;
my_op->deliver_type = &deliver_type;
if(ndx == 0)
{
/* at top level the callback should never be null */
globus_assert(my_op->_op_ent_data_cb != NULL);
globus_thread_blocking_space_callback_push(
globus_i_xio_will_block_cb,
(void *) op,
op->blocking ? GLOBUS_CALLBACK_GLOBAL_SPACE: handle->space,
&wb_ndx);
my_op->_op_ent_data_cb(op, GlobusXIOObjToResult(op->cached_obj),
my_op->_op_ent_nbytes, my_op->user_arg);
globus_thread_blocking_callback_pop(&wb_ndx);
}
else
{
if(my_op->_op_ent_data_cb == NULL)
{
globus_xio_driver_finished_write(op,
GlobusXIOObjToResult(op->cached_obj),
my_op->_op_ent_nbytes);
}
else
{
my_op->_op_ent_data_cb(op,
GlobusXIOObjToResult(op->cached_obj),
my_op->_op_ent_nbytes, my_op->user_arg);
}
}
globus_xio_driver_write_delivered(op, ndx, &deliver_type);
GlobusXIODebugInternalExit();
}
void
globus_l_xio_driver_op_read_kickout(
void * user_arg)
{
globus_xio_operation_type_t deliver_type;
int ndx;
int wb_ndx;
globus_i_xio_handle_t * handle;
globus_i_xio_op_entry_t * my_op;
globus_i_xio_op_t * op;
GlobusXIOName(globus_l_xio_driver_op_read_kickout);
GlobusXIODebugInternalEnter();
op = (globus_i_xio_op_t *) user_arg;
my_op = &op->entry[op->ndx - 1];
op->entry[my_op->prev_ndx].next_ndx = op->ndx;
op->ndx = my_op->prev_ndx;
ndx = op->ndx;
handle = op->_op_handle;
GlobusIXIOClearCancel(op);
/*
* before releasing the op back to the user we can safely set this
* outside of a mutex. Once the users callbcak is called the value
* on the local stack may be changed, theus the magic.
*/
deliver_type = my_op->type;
my_op->deliver_type = &deliver_type;
if(ndx == 0)
{
/* at top level the callback should never be null */
globus_assert(my_op->_op_ent_data_cb != NULL);
globus_thread_blocking_space_callback_push(
globus_i_xio_will_block_cb,
(void *) op,
op->blocking ? GLOBUS_CALLBACK_GLOBAL_SPACE: handle->space,
&wb_ndx);
my_op->_op_ent_data_cb(op, GlobusXIOObjToResult(op->cached_obj),
my_op->_op_ent_nbytes, my_op->user_arg);
globus_thread_blocking_callback_pop(&wb_ndx);
}
else
{
if(my_op->_op_ent_data_cb == NULL)
{
globus_xio_driver_finished_read(op,
GlobusXIOObjToResult(op->cached_obj),
my_op->_op_ent_nbytes);
}
else
{
my_op->_op_ent_data_cb(op,
GlobusXIOObjToResult(op->cached_obj),
my_op->_op_ent_nbytes, my_op->user_arg);
}
}
globus_xio_driver_read_delivered(op, ndx, &deliver_type);
GlobusXIODebugInternalExit();
}
void
globus_l_xio_driver_purge_read_eof(
globus_i_xio_context_entry_t * my_context)
{
globus_i_xio_op_t * tmp_op;
GlobusXIOName(globus_l_xio_driver_purge_read_eof);
GlobusXIODebugInternalEnter();
while(!globus_list_empty(my_context->eof_op_list))
{
/* we can only get here if a eof has been received */
globus_assert(my_context->state ==
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED ||
my_context->state ==
GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED ||
my_context->state ==
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED_AND_CLOSING ||
my_context->state ==
GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED_AND_CLOSING);
tmp_op = (globus_i_xio_op_t *)
globus_list_remove(&my_context->eof_op_list,
my_context->eof_op_list);
globus_assert(tmp_op->entry[tmp_op->ndx - 1].type ==
GLOBUS_XIO_OPERATION_TYPE_READ);
globus_i_xio_register_oneshot(
tmp_op->_op_handle,
globus_l_xio_driver_op_read_kickout,
(void *)tmp_op,
(tmp_op->blocking || !tmp_op->_op_handle)
? GLOBUS_CALLBACK_GLOBAL_SPACE
: tmp_op->_op_handle->space);
}
GlobusXIODebugInternalExit();
}
globus_result_t
globus_i_xio_driver_start_close(
globus_i_xio_op_t * op,
globus_bool_t can_fail)
{
globus_result_t res;
globus_i_xio_handle_t * handle;
globus_i_xio_op_entry_t * my_op;
globus_i_xio_context_t * context;
globus_i_xio_context_entry_t * my_context;
globus_bool_t destroy_handle = GLOBUS_FALSE;
globus_bool_t destroy_context = GLOBUS_FALSE;
GlobusXIOName(globus_i_xio_driver_start_close);
GlobusXIODebugInternalEnter();
op->progress = GLOBUS_TRUE;
op->block_timeout = GLOBUS_FALSE;
my_op = &op->entry[op->ndx - 1];
context = op->_op_context;
handle = op->_op_handle;
my_context = &context->entry[op->ndx - 1];
globus_mutex_lock(&context->mutex);
{
GlobusXIOOpInc(op);
/* make sure the context lives past this op */
context->ref++;
}
globus_mutex_unlock(&context->mutex);
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("[%s:%d] :: Index = %d\n"), _xio_name, __LINE__, op->ndx));
my_op->in_register = GLOBUS_TRUE;
res = my_context->driver->close_func(
my_context->driver_handle,
my_op->close_attr,
op);
my_op->in_register = GLOBUS_FALSE;
if(res != GLOBUS_SUCCESS && !can_fail)
{
my_op->in_register = GLOBUS_TRUE;
globus_xio_driver_finished_close(op, res);
my_op->in_register = GLOBUS_FALSE;
}
if((res == GLOBUS_SUCCESS || !can_fail) && my_op->prev_ndx == 0)
{
while(op->finished_delayed)
{
/* reuse this blocked thread to finish the operation */
op->finished_delayed = GLOBUS_FALSE;
globus_i_xio_driver_resume_op(op);
}
}
globus_mutex_lock(&context->mutex);
{
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
context->ref--;
if(context->ref == 0)
{
destroy_context = GLOBUS_TRUE;
}
}
globus_mutex_unlock(&context->mutex);
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
if(destroy_context)
{
/* the only way we'll be destroying the context is if this was a
* driver op and the handle no longer exists
*/
globus_assert(!destroy_handle);
globus_i_xio_context_destroy(context);
}
GlobusXIODebugInternalExit();
return res;
}
/*
* driver callback kickout
*
* when in a register the finish function kicks this out as a oneshot
*/
void
globus_l_xio_driver_op_close_kickout(
void * user_arg)
{
globus_i_xio_op_t * op;
globus_i_xio_op_entry_t * my_op;
GlobusXIOName(globus_l_xio_driver_op_close_kickout);
GlobusXIODebugInternalEnter();
op = (globus_i_xio_op_t *) user_arg;
my_op = &op->entry[op->ndx - 1];
op->ndx = my_op->prev_ndx;
GlobusIXIOClearCancel(op);
if(my_op->cb != NULL)
{
my_op->cb(
op,
GlobusXIOObjToResult(op->cached_obj),
my_op->user_arg);
}
else
{
globus_xio_driver_finished_close(
op, GlobusXIOObjToResult(op->cached_obj));
}
GlobusXIODebugInternalExit();
}
/*
* driver callback mickout
*
* when in a register the finish function kicks this out as a oneshot
*/
void
globus_l_xio_driver_op_accept_kickout(
void * user_arg)
{
globus_i_xio_op_t * op;
globus_i_xio_op_entry_t * my_op;
GlobusXIOName(globus_l_xio_driver_op_accept_kickout);
GlobusXIODebugInternalEnter();
op = (globus_i_xio_op_t *) user_arg;
my_op = &op->entry[op->ndx - 1];
op->ndx = my_op->prev_ndx;
/* driver's can't cancel accept ops yet, dont need this
* this call only works for regular ops, anyway
*
GlobusIXIOClearCancel(op);
*/
if(my_op->cb != NULL)
{
my_op->cb(
op,
GlobusXIOObjToResult(op->cached_obj),
my_op->user_arg);
}
else
{
globus_xio_driver_finished_accept(
op, NULL, GlobusXIOObjToResult(op->cached_obj));
}
GlobusXIODebugInternalExit();
}
void
globus_l_xio_driver_open_op_kickout(
void * user_arg)
{
globus_i_xio_handle_t * handle;
int ndx = 0;
int wb_ndx;
globus_i_xio_op_entry_t * my_op;
globus_i_xio_op_t * op;
globus_xio_operation_type_t deliver_type;
GlobusXIOName(globus_l_xio_driver_open_op_kickout);
GlobusXIODebugInternalEnter();
op = (globus_i_xio_op_t *) user_arg;
my_op = &op->entry[op->ndx - 1];
op->ndx = my_op->prev_ndx;
ndx = op->ndx;
handle = op->_op_handle;
deliver_type = my_op->type;
my_op->deliver_type =&deliver_type;
GlobusIXIOClearCancel(op);
if(ndx == 0)
{
/* at top level the callback should never be null */
globus_assert(my_op->cb != NULL);
globus_thread_blocking_space_callback_push(
globus_i_xio_will_block_cb,
(void *) op,
op->blocking ? GLOBUS_CALLBACK_GLOBAL_SPACE: handle->space,
&wb_ndx);
my_op->cb(op, GlobusXIOObjToResult(op->cached_obj), my_op->user_arg);
globus_thread_blocking_callback_pop(&wb_ndx);
}
else
{
if(my_op->cb == NULL)
{
globus_xio_driver_finished_open(NULL, op,
GlobusXIOObjToResult(op->cached_obj));
}
else
{
my_op->cb(op,
GlobusXIOObjToResult(op->cached_obj), my_op->user_arg);
}
}
globus_xio_driver_open_delivered(op, ndx, &deliver_type);
GlobusXIODebugInternalExit();
}
/*-************************************************************************
* context driver api funcitons
* ----------------------------
*************************************************************************/
void
globus_i_xio_context_destroy(
globus_i_xio_context_t * xio_context)
{
int ctr;
GlobusXIOName(globus_i_xio_context_destroy);
GlobusXIODebugInternalEnter();
globus_assert(xio_context->ref == 0);
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL(" context @ 0x%x: ref=%d size=%d\n"),
xio_context, xio_context->ref, xio_context->stack_size));
for(ctr = 0; ctr < xio_context->stack_size; ctr++)
{
globus_fifo_destroy(&xio_context->entry[ctr].pending_read_queue);
}
globus_mutex_destroy(&xio_context->mutex);
globus_mutex_destroy(&xio_context->cancel_mutex);
globus_memory_destroy(&xio_context->op_memory);
globus_free(xio_context);
GlobusXIODebugInternalExit();
}
globus_i_xio_context_t *
globus_i_xio_context_create(
int stack_size)
{
globus_i_xio_context_t * xio_context;
int size;
int ctr;
GlobusXIOName(globus_i_xio_context_create);
GlobusXIODebugInternalEnter();
size = sizeof(globus_i_xio_context_t) +
(sizeof(globus_i_xio_context_entry_t) * (stack_size - 1));
xio_context = (globus_i_xio_context_t *) globus_malloc(size);
if(xio_context != NULL)
{
memset(xio_context, '\0', size);
globus_mutex_init(&xio_context->mutex, NULL);
globus_mutex_init(&xio_context->cancel_mutex, NULL);
xio_context->stack_size = stack_size;
globus_memory_init(&xio_context->op_memory,
sizeof(globus_i_xio_op_t) +
(sizeof(globus_i_xio_op_entry_t) *
(stack_size - 1)),
GLOBUS_XIO_HANDLE_DEFAULT_OPERATION_COUNT);
xio_context->ref++;
for(ctr = 0; ctr < xio_context->stack_size; ctr++)
{
xio_context->entry[ctr].whos_my_daddy = xio_context;
globus_fifo_init(&xio_context->entry[ctr].pending_read_queue);
}
}
GlobusXIODebugInternalExit();
return xio_context;
}
/*-************************************************************************
* macro wrapper functions
* -----------------------
*
* this is mainly a compile test, but who knows, someone may want it
*************************************************************************/
void *
globus_i_xio_attr_get_ds(
globus_i_xio_attr_t * attr,
globus_xio_driver_t driver)
{
void * rc;
GlobusIXIOAttrGetDS(rc, attr, driver);
return rc;
}
/*
* read ahead stuff
*/
void
globus_xio_driver_operation_destroy(
globus_xio_operation_t operation)
{
globus_i_xio_context_t * context;
globus_bool_t destroy_context = GLOBUS_FALSE;
globus_i_xio_op_t * op;
GlobusXIOName(globus_xio_driver_operation_destroy);
GlobusXIODebugInternalEnter();
op = operation;
context = op->_op_context;
globus_mutex_lock(&context->mutex);
{
GlobusXIOOpDec(op);
if(op->ref == 0)
{
context->ref--;
if(context->ref == 0)
{
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("[globus_xio_driver_operation_destroy] :: context->ref == 0.\n")));
destroy_context = GLOBUS_TRUE;
}
globus_memory_push_node(&context->op_memory, op);
}
}
globus_mutex_unlock(&context->mutex);
if(destroy_context)
{
globus_i_xio_context_destroy(context);
}
GlobusXIODebugInternalExit();
}
globus_result_t
globus_xio_driver_operation_create(
globus_xio_operation_t * operation,
globus_xio_driver_handle_t driver_handle)
{
globus_i_xio_op_t * op;
globus_i_xio_op_entry_t * my_op;
globus_result_t res;
globus_i_xio_context_t * context;
int index;
GlobusXIOName(globus_xio_driver_operation_create);
GlobusXIODebugEnter();
context = driver_handle->whos_my_daddy;
for(index = 0;
index < context->stack_size &&
&context->entry[index] != driver_handle;
index++)
{
}
if(index == context->stack_size)
{
res = GlobusXIOErrorParameter("driver_handle");
goto err;
}
/* driver_handles are to the drivers below the current one */
index--;
GlobusXIOOperationCreate(op, context);
if(op == NULL)
{
res = GlobusXIOErrorMemory("op");
goto err;
}
op->ndx = index + 1;
op->type = GLOBUS_XIO_OPERATION_TYPE_DRIVER;
op->state = GLOBUS_XIO_OP_STATE_OPERATING;
op->ref = 1;
op->_op_handle = NULL;
op->_op_context = context;
op->_op_handle_timeout_cb = NULL;
my_op = &op->entry[index];
my_op->_op_ent_nbytes = 0;
my_op->_op_ent_wait_for = 0;
my_op->prev_ndx = -1;
my_op->type = GLOBUS_XIO_OPERATION_TYPE_DRIVER;
globus_mutex_lock(&context->mutex);
context->ref++;
globus_mutex_unlock(&context->mutex);
*operation = op;
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_i_xio_driver_attr_cntl(
globus_i_xio_attr_t * attr,
globus_xio_driver_t driver,
int cmd,
va_list ap)
{
char * tmp_str;
globus_result_t res = GLOBUS_SUCCESS;
void * ds;
globus_xio_attr_cmd_t general_cmd;
globus_xio_timeout_server_callback_t server_timeout_cb;
globus_xio_timeout_callback_t timeout_cb;
globus_reltime_t * delay_time;
globus_callback_space_t space;
GlobusXIOName(globus_i_xio_driver_attr_cntl);
GlobusXIODebugEnter();
if(driver != NULL)
{
GlobusIXIOAttrGetDS(ds, attr, driver);
if(ds == NULL)
{
res = driver->attr_init_func(&ds);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
if(attr->ndx >= attr->max)
{
attr->max *= 2;
attr->entry = (globus_i_xio_attr_ent_t *)
globus_realloc(attr->entry, attr->max *
sizeof(globus_i_xio_attr_ent_t));
}
attr->entry[attr->ndx].driver = driver;
attr->entry[attr->ndx].driver_data = ds;
attr->ndx++;
}
/* if the driver is capable of parsing the strings
and this is the string parser command, if there is
no table defined the SET_STRING command will be passed
to the driver. this is fine. they may want to parse it
in their own way */
if(driver->string_table != NULL &&
cmd == GLOBUS_XIO_SET_STRING_OPTIONS)
{
char * opt_str;
opt_str = va_arg(ap, char *);
res = globus_i_xio_string_cntl_parser(
opt_str,
driver->string_table,
ds,
driver->attr_cntl_func);
}
else if (cmd == GLOBUS_XIO_GET_DRIVER_NAME)
{
const char ** conststropt;
conststropt = va_arg(ap, const char **);
*conststropt = driver->name;
}
else
{
res = driver->attr_cntl_func(ds, cmd, ap);
}
if(res != GLOBUS_SUCCESS)
{
goto err;
}
}
else
{
general_cmd = cmd;
switch(general_cmd)
{
case GLOBUS_XIO_ATTR_SET_TIMEOUT_ALL:
timeout_cb = va_arg(ap, globus_xio_timeout_callback_t);
delay_time = va_arg(ap, globus_reltime_t *);
attr->timeout_arg = va_arg(ap, void *);
if(timeout_cb == NULL)
{
timeout_cb = globus_l_xio_timeout_always;
}
attr->open_timeout_cb = timeout_cb;
attr->close_timeout_cb = timeout_cb;
attr->read_timeout_cb = timeout_cb;
attr->write_timeout_cb = timeout_cb;
GlobusTimeReltimeCopy(attr->open_timeout_period, *delay_time);
GlobusTimeReltimeCopy(attr->close_timeout_period, *delay_time);
GlobusTimeReltimeCopy(attr->read_timeout_period, *delay_time);
GlobusTimeReltimeCopy(attr->write_timeout_period, *delay_time);
break;
case GLOBUS_XIO_ATTR_SET_TIMEOUT_OPEN:
timeout_cb = va_arg(ap, globus_xio_timeout_callback_t);
delay_time = va_arg(ap, globus_reltime_t *);
attr->timeout_arg = va_arg(ap, void *);
if(timeout_cb == NULL)
{
timeout_cb = globus_l_xio_timeout_always;
}
attr->open_timeout_cb = timeout_cb;
GlobusTimeReltimeCopy(attr->open_timeout_period, *delay_time);
break;
case GLOBUS_XIO_ATTR_SET_TIMEOUT_CLOSE:
timeout_cb = va_arg(ap, globus_xio_timeout_callback_t);
delay_time = va_arg(ap, globus_reltime_t *);
attr->timeout_arg = va_arg(ap, void *);
if(timeout_cb == NULL)
{
timeout_cb = globus_l_xio_timeout_always;
}
attr->close_timeout_cb = timeout_cb;
GlobusTimeReltimeCopy(attr->close_timeout_period, *delay_time);
break;
case GLOBUS_XIO_ATTR_SET_TIMEOUT_READ:
timeout_cb = va_arg(ap, globus_xio_timeout_callback_t);
delay_time = va_arg(ap, globus_reltime_t *);
attr->timeout_arg = va_arg(ap, void *);
if(timeout_cb == NULL)
{
timeout_cb = globus_l_xio_timeout_always;
}
attr->read_timeout_cb = timeout_cb;
GlobusTimeReltimeCopy(attr->read_timeout_period, *delay_time);
break;
case GLOBUS_XIO_ATTR_SET_TIMEOUT_WRITE:
timeout_cb = va_arg(ap, globus_xio_timeout_callback_t);
delay_time = va_arg(ap, globus_reltime_t *);
attr->timeout_arg = va_arg(ap, void *);
if(timeout_cb == NULL)
{
timeout_cb = globus_l_xio_timeout_always;
}
attr->write_timeout_cb = timeout_cb;
GlobusTimeReltimeCopy(attr->write_timeout_period, *delay_time);
break;
case GLOBUS_XIO_ATTR_SET_TIMEOUT_ACCEPT:
server_timeout_cb =
va_arg(ap, globus_xio_timeout_server_callback_t);
delay_time = va_arg(ap, globus_reltime_t *);
attr->timeout_arg = va_arg(ap, void *);
if(server_timeout_cb == NULL)
{
server_timeout_cb = globus_l_xio_server_timeout_always;
}
attr->accept_timeout_cb = server_timeout_cb;
GlobusTimeReltimeCopy(attr->accept_timeout_period, *delay_time);
break;
case GLOBUS_XIO_ATTR_SET_SPACE:
space = va_arg(ap, globus_callback_space_t);
res = globus_callback_space_reference(space);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
globus_callback_space_destroy(attr->space);
attr->space = space;
break;
case GLOBUS_XIO_ATTR_CLOSE_NO_CANCEL:
attr->no_cancel = va_arg(ap, globus_bool_t);
break;
case GLOBUS_XIO_ATTR_SET_CREDENTIAL:
attr->user_open_cred = va_arg(ap, gss_cred_id_t);
tmp_str = va_arg(ap, char *);
attr->user_open_sbj = globus_libc_strdup(tmp_str);
tmp_str = va_arg(ap, char *);
attr->user_open_username = globus_libc_strdup(tmp_str);
tmp_str = va_arg(ap, char *);
attr->user_open_pw = globus_libc_strdup(tmp_str);
break;
default:
res = GlobusXIOErrorInvalidCommand(general_cmd);
goto err;
}
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_i_xio_driver_dd_cntl(
globus_i_xio_op_t * op,
globus_xio_driver_t driver,
globus_xio_operation_type_t type,
int cmd,
va_list ap)
{
globus_result_t res = GLOBUS_SUCCESS;
int ndx;
int ctr;
void * in_attr = NULL;
globus_xio_driver_attr_cntl_t attr_cntl_func;
GlobusXIOName(globus_i_xio_driver_dd_cntl);
GlobusXIODebugEnter();
if(driver != NULL)
{
ndx = -1;
for(ctr = 0; ctr < op->stack_size && ndx == -1; ctr++)
{
if (op->type == GLOBUS_XIO_OPERATION_TYPE_SERVER_INIT)
{
if (driver == op->_op_server->entry[ctr].driver)
{
if(op->entry[ctr].open_attr == NULL)
{
res =
op->_op_server->entry[ctr].driver->attr_init_func(
&op->entry[ctr].open_attr);
}
in_attr = op->entry[ctr].open_attr;
ndx = ctr;
break;
}
}
else if(driver == op->_op_context->entry[ctr].driver)
{
switch(type)
{
case GLOBUS_XIO_OPERATION_TYPE_OPEN:
if(op->entry[ctr].open_attr == NULL)
{
res =
op->_op_context->entry[ctr].driver->attr_init_func(
&op->entry[ctr].open_attr);
}
in_attr = op->entry[ctr].open_attr;
break;
case GLOBUS_XIO_OPERATION_TYPE_CLOSE:
if(op->entry[ctr].close_attr == NULL)
{
res =
op->_op_context->entry[ctr].driver->attr_init_func(
&op->entry[ctr].close_attr);
}
in_attr = op->entry[ctr].close_attr;
break;
default:
if(op->entry[ctr].dd == NULL)
{
res =
op->_op_context->entry[ctr].driver->attr_init_func(
&op->entry[ctr].dd);
}
in_attr = op->entry[ctr].dd;
break;
}
if(res != GLOBUS_SUCCESS)
{
goto err;
}
ndx = ctr;
break;
}
}
if(ndx == -1)
{
res = GlobusXIOErrorInvalidDriver("not found");
goto err;
}
if (op->type == GLOBUS_XIO_OPERATION_TYPE_SERVER_INIT)
{
attr_cntl_func = op->_op_server->entry[ndx].driver->attr_cntl_func;
}
else
{
attr_cntl_func = op->_op_context->entry[ndx].driver->attr_cntl_func;
}
if (attr_cntl_func)
{
/* if the driver is capable of parsing the strings
and this is the string parser command, if there is
no table defined the SET_STRING command will be passed
to the driver. this is fine. they may want to parse it
in their own way */
if(driver->string_table != NULL &&
cmd == GLOBUS_XIO_SET_STRING_OPTIONS)
{
char * opt_str;
opt_str = va_arg(ap, char *);
res = globus_i_xio_string_cntl_parser(
opt_str,
driver->string_table,
in_attr,
attr_cntl_func);
}
else if (cmd == GLOBUS_XIO_GET_DRIVER_NAME)
{
const char ** conststropt;
conststropt = va_arg(ap, const char **);
*conststropt = driver->name;
res = GLOBUS_SUCCESS;
}
else
{
res = attr_cntl_func(
in_attr,
cmd,
ap);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
}
}
else
{
res = GlobusXIOErrorInvalidDriver(_XIOSL("driver doesn't support dd cntl"));
goto err;
}
}
else
{
globus_off_t * out_offt;
/* could end up here with non-dd attr cntls... none supported at driver
* level yet, so no biggie
*/
switch(cmd)
{
case GLOBUS_XIO_DD_SET_OFFSET:
op->_op_ent_offset = va_arg(ap, globus_off_t);
break;
case GLOBUS_XIO_DD_GET_OFFSET:
out_offt = va_arg(ap, globus_off_t *);
*out_offt = op->_op_ent_offset;
break;
default:
res = GlobusXIOErrorInvalidCommand(cmd);
goto err;
}
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_driver_attr_cntl(
globus_xio_operation_t op,
globus_xio_driver_t driver,
int cmd,
...)
{
int prev_ndx;
globus_result_t res;
va_list ap;
GlobusXIOName(globus_xio_driver_data_descriptor_cntl);
GlobusXIODebugEnter();
if(op == NULL)
{
res = GlobusXIOErrorParameter("op");
goto err;
}
va_start(ap, cmd);
prev_ndx = op->entry[op->ndx - 1].prev_ndx;
res = globus_i_xio_driver_dd_cntl(
op, driver, op->entry[prev_ndx].type, cmd, ap);
va_end(ap);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_driver_data_descriptor_cntl(
globus_xio_operation_t op,
globus_xio_driver_t driver,
int cmd,
...)
{
globus_result_t res;
va_list ap;
GlobusXIOName(globus_xio_driver_data_descriptor_cntl);
GlobusXIODebugEnter();
if(op == NULL)
{
res = GlobusXIOErrorParameter("op");
goto err;
}
va_start(ap, cmd);
res = globus_i_xio_driver_dd_cntl(
op, driver, GLOBUS_XIO_OPERATION_TYPE_DD, cmd, ap);
va_end(ap);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_i_xio_driver_handle_cntl(
globus_i_xio_context_t * context,
int start_ndx,
globus_xio_driver_t driver,
int cmd,
va_list ap)
{
globus_result_t res = GLOBUS_SUCCESS;
int ctr;
globus_bool_t called;
GlobusXIOName(globus_i_xio_driver_handle_cntl);
GlobusXIODebugEnter();
if(context == NULL)
{
res = GlobusXIOErrorParameter("context");
goto err;
}
if(driver != NULL)
{
for(ctr = start_ndx; ctr < context->stack_size; ctr++)
{
called = GLOBUS_FALSE;
if(driver == context->entry[ctr].driver ||
driver == GLOBUS_XIO_QUERY)
{
if(context->entry[ctr].state == GLOBUS_XIO_CONTEXT_STATE_NONE
&& context->entry[ctr].driver->link_cntl_func)
{
/* This driver hasn't been opened yet, slot contains link
* object
*/
res = context->entry[ctr].driver->link_cntl_func(
context->entry[ctr].driver_handle,
cmd,
ap);
called = GLOBUS_TRUE;
}
else if(context->entry[ctr].state !=
GLOBUS_XIO_CONTEXT_STATE_NONE &&
context->entry[ctr].driver->handle_cntl_func)
{
res = context->entry[ctr].driver->handle_cntl_func(
context->entry[ctr].driver_handle,
cmd,
ap);
called = GLOBUS_TRUE;
}
if(called && res == GLOBUS_SUCCESS)
{
break;
}
if(driver == GLOBUS_XIO_QUERY)
{
if(called && res != GLOBUS_SUCCESS &&
globus_xio_error_match(res, GLOBUS_XIO_ERROR_COMMAND))
{
/* try again */
res = GLOBUS_SUCCESS;
}
}
else if(!called)
{
res = GlobusXIOErrorInvalidDriver(
_XIOSL("handle_cntl not supported"));
}
if(res != GLOBUS_SUCCESS)
{
goto err;
}
}
}
if(ctr == context->stack_size)
{
/* none found, throw error */
if(driver != GLOBUS_XIO_QUERY)
{
res = GlobusXIOErrorInvalidDriver(_XIOSL("not found"));
}
else
{
res = GlobusXIOErrorInvalidCommand(cmd);
}
goto err;
}
}
else
{
/* support XIO specific cntls at driver level?? */
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_driver_merge_handle(
globus_xio_operation_t op,
globus_xio_driver_handle_t src_driver_handle)
{
int ctr;
globus_result_t res;
globus_i_xio_context_t * dst_context;
globus_i_xio_context_t * src_context;
GlobusXIOName(globus_xio_driver_merge_handle);
GlobusXIODebugEnter();
if(op == NULL)
{
res = GlobusXIOErrorParameter("op");
goto err;
}
if(src_driver_handle == NULL)
{
res = GlobusXIOErrorParameter("src_driver_handle");
goto err;
}
dst_context = op->_op_context;
src_context = src_driver_handle->whos_my_daddy;
/*
* if they are the same just indicate success
*/
if(dst_context == src_context)
{
return GLOBUS_SUCCESS;
}
if(dst_context->stack_size != src_context->stack_size)
{
res = GlobusXIOErrorParameter("src_driver_handle");
goto err;
}
for(ctr = op->ndx; ctr < dst_context->stack_size; ctr++)
{
/* verify that the drivers are compatible */
if(dst_context->entry[ctr].driver != src_context->entry[ctr].driver)
{
res = GlobusXIOErrorParameter("src_driver_handle");
goto err;
}
dst_context->entry[ctr].whos_my_daddy = dst_context;
dst_context->entry[ctr].driver_handle =
src_context->entry[ctr].driver_handle;
GlobusXIOContextStateChange(&dst_context->entry[ctr],
GLOBUS_XIO_CONTEXT_STATE_OPEN);
}
/* XXX need to remove references on src context so it can be destroyed */
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_driver_handle_cntl(
globus_xio_driver_handle_t driver_handle,
globus_xio_driver_t driver,
int cmd,
...)
{
globus_result_t res;
va_list ap;
globus_i_xio_context_t * context;
int start_ndx = 0;
GlobusXIOName(globus_xio_driver_handle_cntl);
GlobusXIODebugEnter();
if(driver_handle == NULL)
{
res = GlobusXIOErrorParameter("driver_handle");
goto err;
}
context = driver_handle->whos_my_daddy;
if(context == NULL)
{
res = GlobusXIOErrorParameter("op");
goto err;
}
va_start(ap, cmd);
if(driver == GLOBUS_XIO_QUERY)
{
for(; start_ndx < context->stack_size &&
driver_handle != &context->entry[start_ndx]; start_ndx++)
{
}
}
res = globus_i_xio_driver_handle_cntl(context, start_ndx, driver, cmd, ap);
va_end(ap);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_driver_operation_cancel(
globus_xio_driver_handle_t driver_handle,
globus_xio_operation_t operation)
{
globus_result_t res;
globus_i_xio_context_t * context;
globus_i_xio_op_t * op;
int source_ndx;
GlobusXIOName(globus_xio_driver_operation_cancel);
GlobusXIODebugEnter();
op = (globus_i_xio_op_t *) operation;
if(op == NULL)
{
res = GlobusXIOErrorParameter("op");
goto err;
}
context = op->_op_context;
for(source_ndx = 0;
source_ndx < context->stack_size &&
&context->entry[source_ndx] != driver_handle;
source_ndx++)
{
}
if(source_ndx == context->stack_size)
{
res = GlobusXIOErrorParameter("driver_handle");
goto err;
}
/* driver_handles are to the drivers below the current one */
source_ndx--;
globus_mutex_lock(&context->cancel_mutex);
{
res = globus_i_xio_operation_cancel(op, source_ndx);
}
globus_mutex_unlock(&context->cancel_mutex);
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
void
globus_xio_driver_set_eof_received(
globus_xio_operation_t op)
{
globus_i_xio_context_entry_t * my_context;
globus_i_xio_context_t * context;
GlobusXIOName(globus_xio_driver_set_eof_received);
GlobusXIODebugEnter();
context = op->_op_context;
my_context = &context->entry[op->entry[op->ndx - 1].prev_ndx];
globus_mutex_lock(&context->mutex);
{
globus_assert(
my_context->read_operations > 0 &&
_XIOSL("Must be called on behalf of read operations"));
globus_assert(
my_context->state == GLOBUS_XIO_CONTEXT_STATE_OPEN ||
my_context->state == GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED ||
my_context->state ==
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED_AND_CLOSING);
if(my_context->state == GLOBUS_XIO_CONTEXT_STATE_OPEN)
{
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED);
}
}
globus_mutex_unlock(&context->mutex);
GlobusXIODebugExit();
}
globus_bool_t
globus_xio_driver_eof_received(
globus_xio_operation_t op)
{
globus_i_xio_context_entry_t * my_context;
globus_i_xio_context_t * context;
globus_bool_t received = GLOBUS_FALSE;
GlobusXIOName(globus_xio_driver_eof_received);
GlobusXIODebugEnter();
context = op->_op_context;
my_context = &context->entry[op->entry[op->ndx - 1].prev_ndx];
globus_mutex_lock(&context->mutex);
{
globus_assert(
my_context->read_operations > 0 &&
_XIOSL("Must be called on behalf of read operations"));
globus_assert(
my_context->state == GLOBUS_XIO_CONTEXT_STATE_OPEN ||
my_context->state == GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED ||
my_context->state ==
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED_AND_CLOSING);
if(my_context->state == GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED ||
my_context->state ==
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED_AND_CLOSING)
{
received = GLOBUS_TRUE;
}
}
globus_mutex_unlock(&context->mutex);
GlobusXIODebugExit();
return received;
}
/*-*************************************************************************
* driver setup functions
* ----------------------
**************************************************************************/
globus_result_t
globus_xio_driver_init(
globus_xio_driver_t * out_driver,
const char * driver_name,
void * user_data)
{
globus_i_xio_driver_t * driver;
globus_result_t res;
GlobusXIOName(globus_xio_driver_init);
GlobusXIODebugEnter();
driver = (globus_i_xio_driver_t *)
globus_malloc(sizeof(globus_i_xio_driver_t));
if(driver == NULL)
{
res = GlobusXIOErrorMemory("driver");
goto err;
}
memset(driver, '\0', sizeof(globus_i_xio_driver_t));
driver->name = globus_libc_strdup(driver_name);
if(!driver->name)
{
globus_free(driver);
res = GlobusXIOErrorMemory("driver->name");
goto err;
}
driver->user_data = user_data;
*out_driver = driver;
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_driver_get_user_data(
globus_xio_driver_t in_driver,
void ** out_user_data)
{
globus_result_t res;
globus_i_xio_driver_t * driver;
GlobusXIOName(globus_xio_driver_get_user_data);
GlobusXIODebugEnter();
if(in_driver == NULL)
{
res = GlobusXIOErrorMemory("in_driver");
goto err;
}
if(out_user_data == NULL)
{
res = GlobusXIOErrorMemory("out_user_data");
goto err;
}
driver = in_driver;
*out_user_data = driver->user_data;
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_driver_destroy(
globus_xio_driver_t driver)
{
GlobusXIOName(globus_xio_driver_destroy);
GlobusXIODebugEnter();
globus_free(driver->name);
globus_free(driver);
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
}
globus_result_t
globus_xio_driver_set_transport(
globus_xio_driver_t driver,
globus_xio_driver_transport_open_t transport_open_func,
globus_xio_driver_close_t close_func,
globus_xio_driver_read_t read_func,
globus_xio_driver_write_t write_func,
globus_xio_driver_handle_cntl_t handle_cntl_func)
{
GlobusXIOName(globus_xio_driver_set_transport);
GlobusXIODebugEnter();
driver->transport_open_func = transport_open_func;
driver->close_func = close_func;
driver->read_func = read_func;
driver->write_func = write_func;
driver->handle_cntl_func = handle_cntl_func;
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
}
globus_result_t
globus_xio_driver_set_transform(
globus_xio_driver_t driver,
globus_xio_driver_transform_open_t transform_open_func,
globus_xio_driver_close_t close_func,
globus_xio_driver_read_t read_func,
globus_xio_driver_write_t write_func,
globus_xio_driver_handle_cntl_t handle_cntl_func,
globus_xio_driver_push_driver_t push_driver_func)
{
GlobusXIOName(globus_xio_driver_set_transform);
GlobusXIODebugEnter();
driver->transform_open_func = transform_open_func;
driver->close_func = close_func;
driver->read_func = read_func;
driver->write_func = write_func;
driver->handle_cntl_func = handle_cntl_func;
driver->push_driver_func = push_driver_func;
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
}
globus_result_t
globus_xio_driver_set_server(
globus_xio_driver_t driver,
globus_xio_driver_server_init_t server_init_func,
globus_xio_driver_server_accept_t server_accept_func,
globus_xio_driver_server_destroy_t server_destroy_func,
globus_xio_driver_server_cntl_t server_cntl_func,
globus_xio_driver_link_cntl_t link_cntl_func,
globus_xio_driver_link_destroy_t link_destroy_func)
{
GlobusXIOName(globus_xio_driver_set_server);
GlobusXIODebugEnter();
driver->server_init_func = server_init_func;
driver->server_accept_func = server_accept_func;
driver->server_destroy_func = server_destroy_func;
driver->server_cntl_func = server_cntl_func;
driver->link_cntl_func = link_cntl_func;
driver->link_destroy_func = link_destroy_func;
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
}
/**
* @brief Server Pre-Init
* @ingroup globus_xio_driver
* @details
* This function adds a callback to a driver that will be called before
* a server handle is created by XIO. This function has the same signature
* as the server_init_func in the driver, but is always called with a
* NULL contact string. There is no support for calling a pass() or finished()
* function for this interface. It may inspect and modify its attributes
* and operation, but can not directly return any data or set a driver-specific
* server handle value. If this function returns an error result, the server
* create will be aborted.
*
* @param driver
* Driver to associate the function with
* @param server_pre_init_func
* Function to call prior to creating a server
* @retval GLOBUS_SUCCESS
* Success
* @retval GLOBUS_XIO_ERROR_PARAMETER
* Invalid parameter
*/
globus_result_t
globus_xio_driver_set_server_pre_init(
globus_xio_driver_t driver,
globus_xio_driver_server_init_t server_pre_init_func)
{
globus_result_t res = GLOBUS_SUCCESS;
GlobusXIOName(globus_xio_driver_set_server_pre_init);
GlobusXIODebugEnter();
if (!driver)
{
res = GlobusXIOErrorParameter("driver");
goto error;
}
driver->server_pre_init_func = server_pre_init_func;
GlobusXIODebugExit();
return res;
error:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_driver_set_attr(
globus_xio_driver_t driver,
globus_xio_driver_attr_init_t attr_init_func,
globus_xio_driver_attr_copy_t attr_copy_func,
globus_xio_driver_attr_cntl_t attr_cntl_func,
globus_xio_driver_attr_destroy_t attr_destroy_func)
{
GlobusXIOName(globus_xio_driver_set_attr);
GlobusXIODebugEnter();
if(driver == NULL)
{
return GlobusXIOErrorParameter("driver");
}
if(attr_init_func == NULL)
{
return GlobusXIOErrorParameter("attr_init_func");
}
if(attr_copy_func == NULL)
{
return GlobusXIOErrorParameter("attr_copy_func");
}
if(attr_destroy_func == NULL)
{
return GlobusXIOErrorParameter("attr_destroy_func");
}
driver->attr_init_func = attr_init_func;
driver->attr_copy_func = attr_copy_func;
driver->attr_cntl_func = attr_cntl_func;
driver->attr_destroy_func = attr_destroy_func;
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
}
globus_result_t
globus_xio_driver_string_cntl_set_table(
globus_xio_driver_t driver,
globus_xio_string_cntl_table_t * table)
{
globus_result_t result;
GlobusXIOName(globus_xio_driver_set_string_table);
GlobusXIODebugEnter();
if(driver == NULL)
{
result = GlobusXIOErrorParameter("driver");
goto error;
}
if(table == NULL)
{
result = GlobusXIOErrorParameter("table");
goto error;
}
driver->string_table = table;
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
error:
GlobusXIODebugExitWithError();
return result;
}
globus_result_t
globus_xio_driver_handle_string_cntl_set_table(
globus_xio_driver_t driver,
globus_xio_string_cntl_table_t * table)
{
globus_result_t result;
GlobusXIOName(globus_xio_driver_string_cntl_set_table);
GlobusXIODebugEnter();
if(driver == NULL)
{
result = GlobusXIOErrorParameter("driver");
goto error;
}
if(table == NULL)
{
result = GlobusXIOErrorParameter("table");
goto error;
}
driver->handle_string_table = table;
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
error:
GlobusXIODebugExitWithError();
return result;
}
void
globus_xio_operation_block_timeout(
globus_xio_operation_t op)
{
op->block_timeout = GLOBUS_TRUE;
}
void
globus_xio_operation_unblock_timeout(
globus_xio_operation_t op)
{
op->block_timeout = GLOBUS_FALSE;
}
/* note, this is called from win32 threads, therefore, it can never use
* globus mutex calls
*/
void
globus_xio_operation_refresh_timeout(
globus_xio_operation_t op)
{
op->progress = GLOBUS_TRUE;
}
/* returns true if operation already canceled */
globus_bool_t
globus_xio_operation_enable_cancel(
globus_xio_operation_t op,
globus_xio_driver_cancel_callback_t cb,
void * user_arg)
{
globus_bool_t already_canceled;
globus_mutex_t * mutex;
if(op->type == GLOBUS_XIO_OPERATION_TYPE_ACCEPT)
{
mutex = &op->_op_server->mutex;
}
else
{
mutex = &op->_op_context->cancel_mutex;
}
globus_mutex_lock(mutex);
{
already_canceled = op->canceled != 0;
if(op->canceled == 0)
{
op->cancel_cb = cb;
op->cancel_arg = user_arg;
}
}
globus_mutex_unlock(mutex);
return already_canceled;
}
void
globus_xio_operation_disable_cancel(
globus_xio_operation_t op)
{
globus_mutex_t * mutex;
if(op->type == GLOBUS_XIO_OPERATION_TYPE_ACCEPT)
{
mutex = &op->_op_server->mutex;
}
else
{
mutex = &op->_op_context->cancel_mutex;
}
globus_mutex_lock(mutex);
{
op->cancel_cb = NULL;
op->cancel_arg = NULL;
}
globus_mutex_unlock(mutex);
}
/* this is intended to only be used with a lock that a user also holds in the
* cancel callback. I have not thought of the validity outside of that use
*/
globus_bool_t
globus_xio_operation_is_canceled(
globus_xio_operation_t op)
{
return op->canceled != 0;
}
globus_bool_t
globus_xio_driver_operation_is_blocking(
globus_xio_operation_t op)
{
return op->blocking;
}
globus_size_t
globus_xio_operation_get_wait_for(
globus_xio_operation_t op)
{
return op->entry[op->ndx - 1]._op_ent_wait_for;
}
void *
globus_xio_operation_get_driver_specific(
globus_xio_operation_t op)
{
return op->_op_context->entry[op->ndx - 1].driver_handle;
}
globus_xio_driver_t
globus_xio_operation_get_user_driver(
globus_xio_operation_t op)
{
return op->_op_context->entry[op->ndx - 1].driver;
}
/**
* @brief Get the XIO transport driver associated with an op
* @ingroup globus_xio_driver_programming
*/
globus_xio_driver_t
globus_xio_operation_get_transport_user_driver(
globus_xio_operation_t op)
{
globus_xio_driver_t driver;
switch (op->type)
{
case GLOBUS_XIO_OPERATION_TYPE_SERVER_INIT:
case GLOBUS_XIO_OPERATION_TYPE_ACCEPT:
driver = op->_op_server->entry[op->stack_size-1].driver;
break;
default:
driver = op->_op_context->entry[op->stack_size-1].driver;
break;
}
return driver;
}
globus_xio_driver_handle_t
globus_xio_operation_get_driver_handle(
globus_xio_operation_t op)
{
if (op->type == GLOBUS_XIO_OPERATION_TYPE_SERVER_INIT ||
op->type == GLOBUS_XIO_OPERATION_TYPE_ACCEPT)
{
return NULL;
}
return &op->_op_context->entry[op->ndx];
}
globus_xio_driver_handle_t
globus_xio_operation_get_driver_self_handle(
globus_xio_operation_t op)
{
return &op->_op_context->entry[op->ndx - 1];
}
globus_result_t
globus_xio_operation_attr_cntl(
globus_xio_operation_t op,
globus_xio_attr_cmd_t cmd,
...)
{
char ** tmp_ptr;
globus_result_t result;
gss_cred_id_t * out_cred;
va_list ap;
GlobusXIOName(globus_xio_operation_attr_cntl);
if(op == NULL)
{
result = GlobusXIOErrorParameter("op");
goto error_param;
}
va_start(ap, cmd);
switch(cmd)
{
case GLOBUS_XIO_ATTR_GET_CREDENTIAL:
out_cred = va_arg(ap, gss_cred_id_t *);
if(out_cred != NULL)
{
*out_cred = op->user_open_cred;
}
tmp_ptr = va_arg(ap, char **);
if(tmp_ptr != NULL)
{
*tmp_ptr = globus_libc_strdup(op->user_open_sbj);
}
tmp_ptr = va_arg(ap, char **);
if(tmp_ptr != NULL)
{
*tmp_ptr = globus_libc_strdup(op->user_open_username);
}
tmp_ptr = va_arg(ap, char **);
if(tmp_ptr != NULL)
{
*tmp_ptr = globus_libc_strdup(op->user_open_pw);
}
break;
default:
result = GlobusXIOErrorParameter("cmd");
goto error_cmd;
}
va_end(ap);
return GLOBUS_SUCCESS;
error_cmd:
error_param:
va_end(ap);
return result;
}
void *
globus_xio_operation_get_data_descriptor(
globus_xio_operation_t op,
globus_bool_t force_create)
{
if(op->entry[op->ndx - 1].dd == NULL && (op->is_user_dd || force_create))
{
/* need to create a dd */
if(op->_op_context->entry[op->ndx - 1].driver->attr_init_func(
&op->entry[op->ndx - 1].dd) != GLOBUS_SUCCESS)
{
op->entry[op->ndx - 1].dd = NULL;
}
}
return op->entry[op->ndx - 1].dd;
}
globus_result_t
globus_xio_operation_copy_stack(
globus_xio_operation_t op,
globus_xio_stack_t * stack)
{
globus_result_t result;
globus_i_xio_server_t * server;
globus_i_xio_context_t * context;
globus_i_xio_stack_t * istack;
int ndx;
GlobusXIOName(globus_xio_operation_copy_stack);
GlobusXIODebugEnter();
result = globus_xio_stack_init(stack, NULL);
if(result != GLOBUS_SUCCESS)
{
goto error_init;
}
istack = *stack;
switch(op->type)
{
case GLOBUS_XIO_OPERATION_TYPE_SERVER_INIT:
server = op->_op_server;
for(ndx = op->stack_size - 1; ndx > op->ndx; ndx--)
{
istack->size++;
globus_list_insert(
&istack->driver_stack, server->entry[ndx].driver);
}
break;
case GLOBUS_XIO_OPERATION_TYPE_ACCEPT:
server = op->_op_server;
for(ndx = op->stack_size - 1; ndx >= op->ndx; ndx--)
{
istack->size++;
globus_list_insert(
&istack->driver_stack, server->entry[ndx].driver);
}
break;
default:
context = op->_op_context;
for(ndx = op->stack_size - 1; ndx >= op->ndx; ndx--)
{
istack->size++;
globus_list_insert(
&istack->driver_stack, context->entry[ndx].driver);
}
break;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
error_init:
GlobusXIODebugExitWithError();
return result;
}
globus_xio-6.6/PaxHeaders.22691/globus_xio_attr.c 0000644 0000000 0000000 00000000132 14243161125 020106 x ustar 00 0000000 0000000 30 mtime=1653400149.722966433
30 atime=1653401488.601571902
30 ctime=1653403998.749961523
globus_xio-6.6/globus_xio_attr.c 0000664 0001750 0001750 00000121276 14243161125 020257 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "globus_common.h"
#include "globus_i_xio.h"
globus_list_t * globus_i_xio_outstanding_attrs_list;
globus_list_t * globus_i_xio_outstanding_dds_list;
/*******************************************************************
* internal functions
******************************************************************/
/*******************************************************************
* api functions
* -------------
*
* In these we just check parameters, allocate memory and call the
* internal functions.
******************************************************************/
/*
*
*/
globus_result_t
globus_xio_attr_init(
globus_xio_attr_t * attr)
{
globus_result_t res;
globus_i_xio_attr_t * xio_attr;
GlobusXIOName(globus_xio_attr_init);
GlobusXIODebugEnter();
if(attr == NULL)
{
res = GlobusXIOErrorParameter("attr");
goto err;
}
/* allocate the attr */
xio_attr = (globus_i_xio_attr_t *)
globus_calloc(sizeof(globus_i_xio_attr_t), 1);
if(xio_attr == NULL)
{
res = GlobusXIOErrorMemory("attr");
goto err;
}
xio_attr->entry = (globus_i_xio_attr_ent_t *)
globus_calloc(sizeof(globus_i_xio_attr_ent_t) *
GLOBUS_XIO_ATTR_ARRAY_BASE_SIZE, 1);
if(xio_attr->entry == NULL)
{
*attr = GLOBUS_NULL;
globus_free(xio_attr);
res = GlobusXIOErrorMemory("attr->entry");
goto err;
}
/* zero it out */
xio_attr->max = GLOBUS_XIO_ATTR_ARRAY_BASE_SIZE;
xio_attr->space = GLOBUS_CALLBACK_GLOBAL_SPACE;
globus_mutex_lock(&globus_i_xio_mutex);
{
globus_list_insert(&globus_i_xio_outstanding_attrs_list, xio_attr);
}
globus_mutex_unlock(&globus_i_xio_mutex);
*attr = xio_attr;
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_xio_driver_list_ent_t *
globus_xio_driver_list_find_driver(
globus_list_t * driver_list,
const char * driver_name)
{
globus_xio_driver_list_ent_t * ent;
globus_list_t * list;
for(list = driver_list;
!globus_list_empty(list);
list = globus_list_rest(list))
{
ent = (globus_xio_driver_list_ent_t *) globus_list_first(list);
if(strcmp(ent->driver_name, driver_name) == 0)
{
return ent;
}
}
return NULL;
}
void
globus_xio_driver_list_destroy(
globus_list_t * driver_list,
globus_bool_t unload)
{
globus_xio_driver_list_ent_t * ent;
globus_list_t * list;
for(list = driver_list;
!globus_list_empty(list);
list = globus_list_rest(list))
{
ent = (globus_xio_driver_list_ent_t *) globus_list_first(list);
if(ent->driver_name != NULL)
{
globus_free(ent->driver_name);
}
if(ent->opts != NULL)
{
globus_free(ent->opts);
}
if(unload)
{
globus_xio_driver_unload(ent->driver);
}
globus_free(ent);
}
}
/**
* @brief Add a list of driver entries to a stack
* @ingroup GLOBUS_XIO_API
* @details
* This function walks a list of globus_xio_driver_list_ent_t *
* values passed as the driver_list parameter, and pushes them onto the
* XIO stack passed as the stack parameter and sets attributes for those
* drivers in the attr passed as the attr parameter to this function.
*
* @param driver_list
* A list of driver list entries in stack order (transport, followed by
* transform). Each entry may contain a option string for attributes
* to set for this driver.
* @param stack
* A pointer to an XIO stack which will have the drivers pushed onto.
* It must be previously initialized by calling globus_xio_stack_init().
* This function does not overwrite the stack, so the drivers passed in
* the driver list will be pushed on top of any existing drivers in the
* stack.
* @param attr
* A pointer to an XIO attribute which will have the driver-specific
* string options set on it, after the drivers are pushed onto the stack.
* The opts field of the list entries are passed to the
* GLOBUS_XIO_SET_STRING_OPTIONS attr control function. This value
* must be previously initialized by calling globus_xio_attr_init().
* Errors from the attr control function are ignored.
*
* @return If the driver can not be pushed onto the stack, an error
* result is returned; otherwise, GLOBUS_SUCCESS. If an error occurs, some
* of the entries MAY be pushed on to the stack and some attributes may
* have been set in the attr. Both should be destroyed by the caller.
*/
globus_result_t
globus_xio_driver_list_to_stack_attr(
globus_list_t * driver_list,
globus_xio_stack_t stack,
globus_xio_attr_t attr)
{
globus_xio_driver_list_ent_t * ent;
globus_list_t * list;
globus_result_t result = GLOBUS_SUCCESS;
for(list = driver_list;
!globus_list_empty(list);
list = globus_list_rest(list))
{
ent = (globus_xio_driver_list_ent_t *) globus_list_first(list);
result = globus_xio_stack_push_driver(stack, ent->driver);
if (result != GLOBUS_SUCCESS)
{
goto stack_push_fail;
}
if(ent->opts != NULL)
{
/* ignore error */
(void) globus_xio_attr_cntl(
attr,
ent->driver,
GLOBUS_XIO_SET_STRING_OPTIONS,
ent->opts);
}
}
stack_push_fail:
return result;
}
/* globus_xio_driver_list_to_stack_attr() */
globus_result_t
globus_xio_driver_safe_table_from_string(
char * driver_string,
globus_hashtable_t * safe_table)
{
globus_result_t result;
globus_xio_driver_list_ent_t * d_ent;
globus_list_t * driver_list = NULL;
/* take advantage of xio function to load drivers */
result = globus_xio_driver_list_from_string(
driver_string, &driver_list, NULL);
if(result != GLOBUS_SUCCESS)
{
goto error;
}
while(!globus_list_empty(driver_list))
{
d_ent = (globus_xio_driver_list_ent_t *)
globus_list_remove(&driver_list, driver_list);
globus_hashtable_insert(safe_table, d_ent->driver_name, d_ent);
}
return GLOBUS_SUCCESS;
error:
return result;
}
globus_result_t
globus_xio_driver_list_create_ent(
const char * driver_desc,
globus_xio_driver_t driver_in,
globus_bool_t load,
globus_xio_driver_list_ent_t ** ent_out)
{
globus_xio_driver_t driver;
globus_xio_driver_list_ent_t * list_ent;
char * driver_name;
char * opts;
globus_result_t result;
driver_name = strdup(driver_desc);
opts = strchr(driver_name, ':');
if(opts != NULL)
{
*opts = '\0';
opts++;
}
if(load)
{
result = globus_xio_driver_load(driver_name, &driver);
if(result != GLOBUS_SUCCESS)
{
goto error_load;
}
}
else
{
driver = driver_in;
}
list_ent = (globus_xio_driver_list_ent_t *)
globus_calloc(1, sizeof(globus_xio_driver_list_ent_t));
list_ent->opts = globus_libc_strdup(opts);
list_ent->driver = driver;
list_ent->driver_name = driver_name;
list_ent->loaded = load;
*ent_out = list_ent;
return GLOBUS_SUCCESS;
error_load:
globus_free(driver_name);
return result;
}
/* driver list stuff */
globus_result_t
globus_xio_driver_list_from_string(
char * driver_string,
globus_list_t ** driver_list,
globus_hashtable_t * safe_table)
{
globus_result_t result;
globus_bool_t done = GLOBUS_FALSE;
globus_bool_t loaded;
char * opts;
char * ptr;
char * driver_str;
char * driver_name;
char * tmp_str;
globus_xio_driver_t driver;
globus_list_t * list = NULL;
globus_xio_driver_list_ent_t * list_ent;
GlobusXIOName(globus_xio_driver_list_from_string);
*driver_list = NULL;
if(driver_string == NULL)
{
result = GlobusXIOErrorParameter("driver_string");
goto error_param;
}
driver_str = globus_libc_strdup(driver_string);
tmp_str = driver_str;
while(!done)
{
loaded = GLOBUS_FALSE;
driver_name = tmp_str;
ptr = strchr(driver_name, ',');
if(ptr != NULL)
{
*ptr = '\0';
tmp_str = ptr+1;
}
else
{
done = GLOBUS_TRUE;
}
opts = strchr(driver_name, ':');
if(opts != NULL)
{
*opts = '\0';
opts++;
/* decode the string */
globus_url_string_hex_decode(opts);
}
/* check against the safe list */
if(safe_table != NULL)
{
char * err_str;
list_ent = (globus_xio_driver_list_ent_t *)
globus_hashtable_lookup(safe_table, driver_name);
if(list_ent == NULL)
{
err_str = globus_common_create_string(
"%s driver not whitelisted", driver_name);
result = GlobusXIOErrorParameter(err_str);
globus_free(err_str);
goto error_load;
}
driver = list_ent->driver;
}
else
{
result = globus_xio_driver_load(driver_name, &driver);
if(result != GLOBUS_SUCCESS)
{
goto error_load;
}
loaded = GLOBUS_TRUE;
}
list_ent = (globus_xio_driver_list_ent_t *)
globus_calloc(1, sizeof(globus_xio_driver_list_ent_t));
list_ent->opts = globus_libc_strdup(opts);
list_ent->driver = driver;
list_ent->driver_name = globus_libc_strdup(driver_name);
list_ent->loaded = loaded;
globus_list_insert(&list, list_ent);
}
globus_free(driver_str);
/* reverse list */
while(!globus_list_empty(list))
{
globus_list_insert(driver_list, globus_list_first(list));
globus_list_remove(&list, list);
}
return GLOBUS_SUCCESS;
error_load:
globus_free(driver_str);
while(!globus_list_empty(list))
{
list_ent = (globus_xio_driver_list_ent_t *)
globus_list_remove(&list, list);
if(list_ent->loaded)
{
globus_xio_driver_unload(list_ent->driver);
}
globus_free(list_ent->driver_name);
if(list_ent->opts != NULL)
{
globus_free(list_ent->opts);
}
globus_free(list_ent);
}
error_param:
return result;
}
/*
*
*/
globus_result_t
globus_xio_attr_cntl(
globus_xio_attr_t user_attr,
globus_xio_driver_t driver,
int cmd,
...)
{
va_list ap;
globus_result_t res;
globus_i_xio_attr_t * attr;
GlobusXIOName(globus_xio_attr_cntl);
GlobusXIODebugEnter();
if(user_attr == NULL)
{
res = GlobusXIOErrorParameter("user_attr");
goto err;
}
attr = user_attr;
va_start(ap, cmd);
res = globus_i_xio_driver_attr_cntl(attr, driver, cmd, ap);
if(res != GLOBUS_SUCCESS)
{
va_end(ap);
goto err;
}
va_end(ap);
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
/*
*
*/
globus_result_t
globus_xio_attr_destroy(
globus_xio_attr_t attr)
{
int ctr;
globus_result_t res = GLOBUS_SUCCESS;
globus_result_t tmp_res;
GlobusXIOName(globus_xio_attr_destroy);
GlobusXIODebugEnter();
if(attr == NULL)
{
res = GlobusXIOErrorParameter("attr");
goto err;
}
globus_mutex_lock(&globus_i_xio_mutex);
{
if(!attr->unloaded)
{
for(ctr = 0; ctr < attr->ndx; ctr++)
{
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[globus_xio_attr_destroy]: destroying attr @0x%x "
"driver @0x%x, %s\n"),
attr,
attr->entry[ctr].driver,
attr->entry[ctr].driver->name));
/* report the last seen error but be sure to attempt to clean
them all */
tmp_res = attr->entry[ctr].driver->attr_destroy_func(
attr->entry[ctr].driver_data);
if(tmp_res != GLOBUS_SUCCESS)
{
res = tmp_res;
}
}
globus_list_remove(
&globus_i_xio_outstanding_attrs_list,
globus_list_search(
globus_i_xio_outstanding_attrs_list, attr));
}
}
globus_mutex_unlock(&globus_i_xio_mutex);
if(attr->user_open_sbj)
{
globus_free(attr->user_open_sbj);
}
if(attr->user_open_username)
{
globus_free(attr->user_open_username);
}
if(attr->user_open_pw)
{
globus_free(attr->user_open_pw);
}
globus_callback_space_destroy(attr->space);
globus_free(attr->entry);
globus_free(attr);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_attr_copy(
globus_xio_attr_t * dst,
globus_xio_attr_t src)
{
globus_i_xio_attr_t * xio_attr_src;
globus_i_xio_attr_t * xio_attr_dst;
globus_result_t res;
int ctr;
int ctr2;
GlobusXIOName(globus_xio_attr_copy);
GlobusXIODebugEnter();
if(dst == NULL)
{
res = GlobusXIOErrorParameter("dst");
goto err;
}
if(src == NULL)
{
res = GlobusXIOErrorParameter("src");
goto err;
}
xio_attr_src = src;
xio_attr_dst = (globus_i_xio_attr_t *)
globus_malloc(sizeof(globus_i_xio_attr_t));
/* check for memory alloc failure */
if(xio_attr_dst == NULL)
{
res = GlobusXIOErrorMemory("xio_attr_dst");
goto err;
}
memset(xio_attr_dst, 0, sizeof(globus_i_xio_attr_t));
xio_attr_dst->entry = (globus_i_xio_attr_ent_t *)
globus_malloc(sizeof(globus_i_xio_attr_ent_t) *
GLOBUS_XIO_ATTR_ARRAY_BASE_SIZE);
if(xio_attr_dst->entry == NULL)
{
globus_free(xio_attr_dst);
res = GlobusXIOErrorMemory("xio_attr_dst->entry");
goto err;
}
memset(xio_attr_dst->entry, 0,
sizeof(globus_i_xio_attr_ent_t) * GLOBUS_XIO_ATTR_ARRAY_BASE_SIZE);
/* copy all general attrs */
xio_attr_dst->max = xio_attr_src->max;
xio_attr_dst->ndx = xio_attr_src->ndx;
xio_attr_dst->space = xio_attr_src->space;
globus_callback_space_reference(xio_attr_dst->space);
xio_attr_dst->open_timeout_cb = xio_attr_src->open_timeout_cb;
xio_attr_dst->open_timeout_period = xio_attr_src->open_timeout_period;
xio_attr_dst->read_timeout_cb = xio_attr_src->read_timeout_cb;
xio_attr_dst->read_timeout_period = xio_attr_src->read_timeout_period;
xio_attr_dst->write_timeout_cb = xio_attr_src->write_timeout_cb;
xio_attr_dst->write_timeout_period = xio_attr_src->write_timeout_period;
xio_attr_dst->close_timeout_cb = xio_attr_src->close_timeout_cb;
xio_attr_dst->close_timeout_period = xio_attr_src->close_timeout_period;
xio_attr_dst->accept_timeout_cb = xio_attr_src->accept_timeout_cb;
xio_attr_dst->accept_timeout_period = xio_attr_src->accept_timeout_period;
xio_attr_dst->cancel_open = xio_attr_src->cancel_open;
xio_attr_dst->cancel_close = xio_attr_src->cancel_close;
xio_attr_dst->cancel_read = xio_attr_src->cancel_read;
xio_attr_dst->cancel_write = xio_attr_src->cancel_write;
xio_attr_dst->no_cancel = xio_attr_src->no_cancel;
xio_attr_dst->timeout_arg = xio_attr_src->timeout_arg;
for(ctr = 0; ctr < xio_attr_dst->ndx; ctr++)
{
xio_attr_dst->entry[ctr].driver = xio_attr_src->entry[ctr].driver;
res = xio_attr_dst->entry[ctr].driver->attr_copy_func(
&xio_attr_dst->entry[ctr].driver_data,
xio_attr_src->entry[ctr].driver_data);
if(res != GLOBUS_SUCCESS)
{
for(ctr2 = 0; ctr2 < ctr; ctr2++)
{
/* ignore result here */
xio_attr_dst->entry[ctr].driver->attr_destroy_func(
xio_attr_dst->entry[ctr].driver_data);
}
globus_free(xio_attr_dst->entry);
globus_free(xio_attr_dst);
goto err;
}
}
globus_mutex_lock(&globus_i_xio_mutex);
{
globus_list_insert(&globus_i_xio_outstanding_attrs_list, xio_attr_dst);
}
globus_mutex_unlock(&globus_i_xio_mutex);
*dst = xio_attr_dst;
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
/*******************************************************************
* data descriptor stuff
******************************************************************/
/*
* the main difference between a dd and an attr is that the DD
* has the driver specific data in order of the drivers in the handle
*
* the same internal data structures are used. the only difference
* in accessing these data structures is the assumptoin of order.
*/
/*
*
*/
globus_result_t
globus_xio_data_descriptor_init(
globus_xio_data_descriptor_t * data_desc,
globus_xio_handle_t handle)
{
globus_result_t res = GLOBUS_SUCCESS;
globus_i_xio_op_t * op;
globus_i_xio_context_t * context;
GlobusXIOName(globus_xio_data_descriptor_init);
GlobusXIODebugEnter();
if(data_desc == NULL)
{
res = GlobusXIOErrorParameter("data_desc");
goto err_parm;
}
if(handle == NULL)
{
res = GlobusXIOErrorParameter("handle");
goto err;
}
context = handle->context;
globus_mutex_lock(&context->mutex);
{
GlobusXIOOperationCreate(op, context);
if(op != NULL)
{
op->type = GLOBUS_XIO_OPERATION_TYPE_DD;
handle->ref++;
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[globus_xio_data_descriptor_init] :: handle ref at %d.\n"), handle->ref));
op->_op_handle = handle;
op->ref = 1;
op->is_user_dd = GLOBUS_TRUE;
}
else
{
res = GlobusXIOErrorMemory("xio_dd");
}
}
globus_mutex_unlock(&context->mutex);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
*data_desc = op;
globus_mutex_lock(&globus_i_xio_mutex);
{
globus_list_insert(&globus_i_xio_outstanding_dds_list, op);
}
globus_mutex_unlock(&globus_i_xio_mutex);
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
*data_desc = NULL;
err_parm:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_data_descriptor_destroy(
globus_xio_data_descriptor_t data_desc)
{
globus_result_t res = GLOBUS_SUCCESS;
globus_i_xio_op_t * op;
globus_i_xio_handle_t * handle;
globus_bool_t destroy_handle = GLOBUS_FALSE;
globus_list_t * node;
GlobusXIOName(globus_xio_data_descriptor_destroy);
GlobusXIODebugEnter();
if(data_desc == NULL)
{
res = GlobusXIOErrorParameter("data_desc");
goto err;
}
op = (globus_i_xio_op_t *) data_desc;
globus_mutex_lock(&globus_i_xio_mutex);
{
/* make sure we haven't destroyed it already */
node = globus_list_search(globus_i_xio_outstanding_dds_list, op);
if(node)
{
globus_list_remove(&globus_i_xio_outstanding_dds_list, node);
}
}
globus_mutex_unlock(&globus_i_xio_mutex);
if(node == NULL)
{
res = GlobusXIOErrorParameter("data_desc already destroyed");
goto err;
}
handle = op->_op_handle;
globus_mutex_lock(&handle->context->mutex);
{
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
}
globus_mutex_unlock(&handle->context->mutex);
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_data_descriptor_cntl(
globus_xio_data_descriptor_t data_desc,
globus_xio_driver_t driver,
int cmd,
...)
{
globus_result_t res;
globus_i_xio_op_t * op;
va_list ap;
GlobusXIOName(globus_xio_data_descriptor_cntl);
GlobusXIODebugEnter();
if(data_desc == NULL)
{
res = GlobusXIOErrorParameter("data_desc");
goto err;
}
op = (globus_i_xio_op_t *) data_desc;
va_start(ap, cmd);
res = globus_i_xio_driver_dd_cntl(op, driver, op->type, cmd, ap);
va_end(ap);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_data_descriptor_copy(
globus_xio_data_descriptor_t * dst,
globus_xio_data_descriptor_t src)
{
globus_i_xio_op_t * op_src;
globus_i_xio_op_t * op_dst;
globus_result_t res;
int ctr;
int ctr2;
GlobusXIOName(globus_xio_data_descriptor_copy);
GlobusXIODebugEnter();
if(dst == NULL)
{
res = GlobusXIOErrorParameter("dst");
goto err;
}
if(src == NULL)
{
res = GlobusXIOErrorParameter("src");
goto err;
}
op_src = src;
res = globus_xio_data_descriptor_init(&op_dst, op_src->_op_handle);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
for(ctr = 0; ctr < op_src->stack_size; ctr++)
{
res = op_dst->_op_context->entry[ctr].driver->attr_copy_func(
&op_dst->entry[ctr].dd,
op_src->entry[ctr].dd);
if(res != GLOBUS_SUCCESS)
{
for(ctr2 = 0; ctr2 < ctr; ctr2++)
{
/* ignore result here */
op_dst->_op_context->entry[ctr].driver->attr_destroy_func(
op_dst->entry[ctr].dd);
}
globus_memory_push_node(&op_dst->_op_context->op_memory, op_dst);
goto err_destroy_op;
}
}
*dst = op_dst;
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err_destroy_op:
globus_xio_data_descriptor_destroy(op_dst);
err:
GlobusXIODebugExitWithError();
return res;
}
/************************************************************************
* stack functions
***********************************************************************/
globus_result_t
globus_xio_stack_init(
globus_xio_stack_t * stack,
globus_xio_attr_t stack_attr)
{
globus_i_xio_stack_t * xio_stack;
GlobusXIOName(globus_xio_stack_init);
GlobusXIODebugEnter();
if(stack == NULL)
{
GlobusXIODebugExitWithError();
return GlobusXIOErrorParameter("stack");
}
xio_stack = globus_malloc(sizeof(globus_i_xio_stack_t));
memset(xio_stack, '\0', sizeof(globus_i_xio_stack_t));
*stack = xio_stack;
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
}
globus_result_t
globus_xio_stack_copy(
globus_xio_stack_t * dst,
globus_xio_stack_t src)
{
globus_i_xio_stack_t * xio_stack_src;
globus_i_xio_stack_t * xio_stack_dst;
globus_result_t res;
GlobusXIOName(globus_xio_stack_push_driver);
GlobusXIODebugEnter();
if(dst == NULL)
{
res = GlobusXIOErrorParameter("dst");
goto err;
}
if(src == NULL)
{
res = GlobusXIOErrorParameter("src");
goto err;
}
xio_stack_src = src;
xio_stack_dst = (globus_i_xio_stack_t *)
globus_calloc(1, sizeof(globus_i_xio_stack_t));
/* check for memory alloc failure */
if(xio_stack_dst == NULL)
{
res = GlobusXIOErrorMemory("xio_stack_dst");
goto err;
}
xio_stack_dst->size = xio_stack_src->size;
xio_stack_dst->driver_stack = globus_list_copy(
xio_stack_src->driver_stack);
*dst = xio_stack_dst;
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_stack_push_driver(
globus_xio_stack_t stack,
globus_xio_driver_t driver)
{
globus_xio_driver_t p_d;
globus_i_xio_stack_t * xio_stack;
globus_result_t res = GLOBUS_SUCCESS;
GlobusXIOName(globus_xio_stack_push_driver);
GlobusXIODebugEnter();
if(stack == NULL)
{
res = GlobusXIOErrorParameter("stack");
goto err;
}
if(driver == NULL)
{
res = GlobusXIOErrorParameter("driver");
goto err;
}
xio_stack = (globus_i_xio_stack_t *) stack;
/* if in the transport position and has a push stack */
if(driver->push_driver_func != NULL && xio_stack->pushing_driver != driver)
{
p_d = xio_stack->pushing_driver;
xio_stack->pushing_driver = driver;
res = driver->push_driver_func(driver, xio_stack);
xio_stack->pushing_driver = p_d;
if(res != GLOBUS_SUCCESS)
{
goto err;
}
}
/* if a transport driver position */
else if(xio_stack->size == 0)
{
if(driver->transport_open_func == NULL)
{
res = GlobusXIOErrorInvalidDriver(
_XIOSL("open function not defined"));
goto err;
}
else
{
xio_stack->size++;
globus_list_insert(&xio_stack->driver_stack, driver);
}
}
else if(driver->transport_open_func != NULL)
{
res = GlobusXIOErrorInvalidDriver(
_XIOSL("transport can only be at bottom of stack"));
goto err;
}
else
{
xio_stack->size++;
globus_list_insert(&xio_stack->driver_stack, driver);
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_stack_destroy(
globus_xio_stack_t stack)
{
globus_result_t res;
GlobusXIOName(globus_xio_stack_destroy);
GlobusXIODebugEnter();
if(stack == NULL)
{
res = GlobusXIOErrorParameter("stack");
goto err;
}
globus_list_free(stack->driver_stack);
globus_free(stack);
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
/* STRING PARSING ATTR SETTING */
globus_result_t
globus_i_xio_string_cntl_parser(
const char * env_str,
globus_xio_string_cntl_table_t * table,
void * attr,
globus_xio_driver_attr_cntl_t cntl_func)
{
int i;
char * key;
char * val;
char * tmp_s;
globus_list_t * list;
globus_object_t * error = NULL;
globus_result_t res = GLOBUS_SUCCESS;
GlobusXIOName(globus_i_xio_string_cntl_parser);
list = globus_list_from_string(env_str, ';', NULL);
while(!globus_list_empty(list))
{
key = (char *) globus_list_remove(&list, list);
tmp_s = strchr(key, '=');
if(tmp_s != NULL)
{
*tmp_s = '\0';
val = tmp_s + 1;
for(i = 0; table[i].key != NULL; i++)
{
/* if we have a match */
if(strcmp(table[i].key, key) == 0)
{
res = table[i].parse_func(
attr, key, val, table[i].cmd, cntl_func);
if(res != GLOBUS_SUCCESS)
{
/* restore '=' */
*tmp_s = '=';
res = GlobusXIOErrorWrapFailedWithMessage(
res, "String cntl '%s' failed", key);
}
break;
}
}
if(!table[i].key)
{
res = GlobusXIOErrorParameter(key);
}
}
else
{
res = GlobusXIOErrorParameter(key);
}
if(res != GLOBUS_SUCCESS)
{
if(!error)
{
error = globus_error_construct_multiple(
GLOBUS_XIO_MODULE,
GLOBUS_XIO_ERROR_PARAMETER,
"One or more of the string cntls failed");
}
globus_error_mutliple_add_chain(
error, globus_error_get(res), NULL);
}
globus_free(key);
}
if (error != GLOBUS_SUCCESS)
{
return globus_error_put(error);
}
else
{
return GLOBUS_SUCCESS;
}
}
globus_result_t
globus_xio_string_cntl_bouncer(
globus_xio_driver_attr_cntl_t cntl_func,
void * attr,
int cmd,
...)
{
globus_result_t result;
va_list ap;
va_start(ap, cmd);
result = cntl_func(attr, cmd, ap);
va_end(ap);
return result;
}
static
int
globus_xio_string_cntl_tb_kmgint(
const char * arg,
globus_off_t * out_i)
{
int i;
int sc;
GlobusXIOName(globus_xio_string_cntl_tb_kmgint);
GlobusXIODebugEnter();
sc = sscanf(arg, "%d", &i);
if(sc != 1)
{
return 1;
}
if(strchr(arg, 'K') != NULL)
{
*out_i = (globus_off_t)i * 1024;
}
else if(strchr(arg, 'M') != NULL)
{
*out_i = (globus_off_t)i * 1024 * 1024;
}
else if(strchr(arg, 'G') != NULL)
{
*out_i = (globus_off_t)i * 1024 * 1024 * 1024;
}
else if(strchr(arg, 'g') != NULL)
{
*out_i = (globus_off_t)i * 1024 * 1024 * 1024;
*out_i = *out_i / 8;
}
else if(strchr(arg, 'm') != NULL)
{
*out_i = (globus_off_t)i * 1024 * 1024;
*out_i = *out_i / 8;
}
else if(strchr(arg, 'k') != NULL)
{
*out_i = (globus_off_t)i * 1024;
*out_i = *out_i / 8;
}
else if(strchr(arg, 'b') != NULL)
{
*out_i = (globus_off_t)i;
*out_i = *out_i / 8;
}
else
{
*out_i = (globus_off_t)i;
}
return 0;
}
globus_result_t
globus_xio_string_cntl_formated_off(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func)
{
int sc;
globus_off_t o;
globus_result_t result = GLOBUS_SUCCESS;
GlobusXIOName(globus_xio_string_cntl_formated_off);
GlobusXIODebugEnter();
sc = globus_xio_string_cntl_tb_kmgint(val, &o);
if(sc != 0)
{
result = GlobusXIOErrorParse(val);
}
else
{
result = globus_xio_string_cntl_bouncer(cntl_func, attr, cmd, o);
}
GlobusXIODebugExit();
return result;
}
globus_result_t
globus_xio_string_cntl_formated_int(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func)
{
int sc;
int i;
globus_off_t o;
globus_result_t result = GLOBUS_SUCCESS;
GlobusXIOName(globus_xio_string_cntl_formated_int);
GlobusXIODebugEnter();
sc = globus_xio_string_cntl_tb_kmgint(val, &o);
if(sc != 0)
{
result = GlobusXIOErrorParse(val);
}
else
{
i = (int) o;
result = globus_xio_string_cntl_bouncer(cntl_func, attr, cmd, i);
}
GlobusXIODebugExit();
return result;
}
globus_result_t
globus_xio_string_cntl_int(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func)
{
int sc;
int i;
globus_result_t result = GLOBUS_SUCCESS;
GlobusXIOName(globus_xio_string_cntl_int);
GlobusXIODebugEnter();
sc = sscanf(val, "%d", &i);
if(sc != 1)
{
result = GlobusXIOErrorParse(val);
}
else
{
result = globus_xio_string_cntl_bouncer(cntl_func, attr, cmd, i);
}
GlobusXIODebugExit();
return result;
}
globus_result_t
globus_xio_string_cntl_int_int(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func)
{
int sc;
int i;
int j;
char * tmp_s;
char * new_val;
globus_result_t result = GLOBUS_SUCCESS;
GlobusXIOName(globus_xio_string_cntl_int_int);
GlobusXIODebugEnter();
/* turn all non digits into spaces for the scanf easiness */
tmp_s = strdup(val);
if(tmp_s == NULL)
{
result = GlobusXIOErrorParse(val);
return result;
}
new_val = tmp_s;
while(*tmp_s != '\0')
{
if(!isdigit(*tmp_s))
{
*tmp_s = ' ';
}
tmp_s++;
}
sc = sscanf(new_val, "%d %d", &i, &j);
free(new_val);
if(sc != 2)
{
result = GlobusXIOErrorParse(val);
}
else
{
result = globus_xio_string_cntl_bouncer(cntl_func, attr, cmd, i, j);
}
GlobusXIODebugExit();
return result;
}
globus_result_t
globus_xio_string_cntl_float(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func)
{
int sc;
float f;
globus_result_t result = GLOBUS_SUCCESS;
GlobusXIOName(globus_xio_string_cntl_float);
GlobusXIODebugEnter();
sc = sscanf(val, "%f", &f);
if(sc != 1)
{
result = GlobusXIOErrorParse(val);
}
else
{
result = globus_xio_string_cntl_bouncer(cntl_func, attr, cmd, f);
}
GlobusXIODebugExit();
return result;
}
globus_result_t
globus_xio_string_cntl_string(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func)
{
globus_result_t result = GLOBUS_SUCCESS;
GlobusXIOName(globus_xio_string_cntl_string);
GlobusXIODebugEnter();
result = globus_xio_string_cntl_bouncer(cntl_func, attr, cmd, val);
GlobusXIODebugExit();
return result;
}
globus_result_t
globus_xio_string_cntl_bool(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func)
{
int sc;
int i;
globus_bool_t found = GLOBUS_FALSE;
globus_bool_t b;
globus_result_t result = GLOBUS_SUCCESS;
GlobusXIOName(globus_xio_string_cntl_bool);
GlobusXIODebugEnter();
if(strcasecmp(val, "yes") == 0)
{
b = GLOBUS_TRUE;
found = GLOBUS_TRUE;
}
else if(strcasecmp(val, "y") == 0)
{
b = GLOBUS_TRUE;
found = GLOBUS_TRUE;
}
else if(strcasecmp(val, "true") == 0)
{
b = GLOBUS_TRUE;
found = GLOBUS_TRUE;
}
else if(strcasecmp(val, "t") == 0)
{
b = GLOBUS_TRUE;
found = GLOBUS_TRUE;
}
else if(strcasecmp(val, "no") == 0)
{
b = GLOBUS_FALSE;
found = GLOBUS_TRUE;
}
else if(strcasecmp(val, "n") == 0)
{
b = GLOBUS_FALSE;
found = GLOBUS_TRUE;
}
else if(strcasecmp(val, "false") == 0)
{
b = GLOBUS_FALSE;
found = GLOBUS_TRUE;
}
else if(strcasecmp(val, "f") == 0)
{
b = GLOBUS_FALSE;
found = GLOBUS_TRUE;
}
else
{
sc = sscanf(val, "%d", &i);
if(sc == 1)
{
b = i;
found = GLOBUS_TRUE;
}
}
if(found)
{
result = globus_xio_string_cntl_bouncer(cntl_func, attr, cmd, b);
}
else
{
result = GlobusXIOErrorParse(val);
}
GlobusXIODebugExit();
return result;
}
globus_result_t
globus_xio_string_cntl_string_list(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func)
{
int i = 0;
globus_list_t * val_list;
globus_list_t * list;
char ** argv;
int argc;
globus_result_t result;
int del;
/* delimitor is the first character */
if(val == NULL)
{
return GLOBUS_SUCCESS;
}
del = (int)*val;
val++;
val_list = globus_list_from_string(val, del, NULL);
list = val_list;
argc = globus_list_size(list);
argv = (char **) calloc(argc+1, sizeof(char *));
i = argc - 1;
while(!globus_list_empty(list))
{
argv[i] = (char *)globus_list_first(list);
list = globus_list_rest(list);
i--;
}
result = globus_xio_string_cntl_bouncer(cntl_func, attr, cmd, argv);
globus_list_destroy_all(val_list, globus_libc_free);
globus_free(argv);
return result;
}
globus_xio-6.6/PaxHeaders.22691/globus_xio_timeout.c 0000644 0000000 0000000 00000000132 14243161125 020622 x ustar 00 0000000 0000000 30 mtime=1653400149.725966402
30 atime=1653401488.817569765
30 ctime=1653403998.750961513
globus_xio-6.6/globus_xio_timeout.c 0000664 0001750 0001750 00000022165 14243161125 020770 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "globus_i_xio.h"
#define GLOBUS_L_XIO_TIMER_MAX_POLL 60 /* seconds */
typedef struct globus_i_xio_timer_entry_s
{
void * datum;
globus_bool_t * progress_ptr;
globus_i_xio_timer_cb_t timer_cb;
globus_reltime_t rel_timeout;
globus_abstime_t abs_timeout;
} globus_i_xio_timer_entry_t;
void
globus_i_xio_timer_poller_callback(
void * user_arg);
void
globus_i_xio_timer_init(
globus_i_xio_timer_t * timer)
{
GlobusXIOName(globus_i_xio_timer_init);
GlobusXIODebugInternalEnter();
globus_mutex_init(&timer->mutex, NULL);
globus_cond_init(&timer->cond, NULL);
timer->op_list = NULL;
timer->running = GLOBUS_FALSE;
globus_callback_space_register_periodic(
&timer->periodic_handle,
&globus_i_reltime_infinity,
&globus_i_reltime_infinity,
globus_i_xio_timer_poller_callback,
(void *)timer,
GLOBUS_CALLBACK_GLOBAL_SPACE);
GlobusXIODebugInternalExit();
}
void
globus_l_xio_timer_unregister_cb(
void * user_args)
{
globus_i_xio_timer_t * timer;
GlobusXIOName(globus_l_xio_timer_unregister_cb);
GlobusXIODebugInternalEnter();
timer = (globus_i_xio_timer_t *) user_args;
globus_mutex_lock(&timer->mutex);
{
timer->running = GLOBUS_FALSE;
globus_cond_signal(&timer->cond);
}
globus_mutex_unlock(&timer->mutex);
/* GlobusXIODebugInternalExit(); having this in can cause core dumps */
}
void
globus_i_xio_timer_destroy(
globus_i_xio_timer_t * timer)
{
globus_result_t res;
GlobusXIOName(globus_i_xio_timer_destroy);
GlobusXIODebugInternalEnter();
globus_mutex_lock(&timer->mutex);
{
/* reuse a bool */
timer->running = GLOBUS_TRUE;
res = globus_callback_unregister(
timer->periodic_handle,
globus_l_xio_timer_unregister_cb,
(void *)timer,
NULL);
/* logic of this code should prevent this from ever failing */
globus_assert(res == GLOBUS_SUCCESS);
while(timer->running)
{
globus_cond_wait(&timer->cond, &timer->mutex);
}
}
globus_mutex_unlock(&timer->mutex);
/* if the list is not empty i am not gonna complain */
globus_mutex_destroy(&timer->mutex);
GlobusXIODebugInternalExit();
}
void
globus_i_xio_timer_register_timeout(
globus_i_xio_timer_t * timer,
void * datum,
globus_bool_t * progress_ptr,
globus_i_xio_timer_cb_t timeout_cb,
globus_reltime_t * timeout)
{
globus_i_xio_timer_entry_t * entry;
globus_result_t res;
globus_reltime_t poll_time;
GlobusXIOName(globus_i_xio_timer_register_timeout);
GlobusXIODebugInternalEnter();
entry = globus_malloc(sizeof(globus_i_xio_timer_entry_t));
entry->datum = datum;
entry->progress_ptr = progress_ptr;
entry->timer_cb = timeout_cb;
GlobusTimeReltimeCopy(entry->rel_timeout, *timeout);
GlobusTimeReltimeCopy(poll_time, entry->rel_timeout);
/* limit poll time */
if(poll_time.tv_sec > GLOBUS_L_XIO_TIMER_MAX_POLL)
{
GlobusTimeReltimeSet(poll_time, GLOBUS_L_XIO_TIMER_MAX_POLL, 0);
}
/* expire immediately to force setting of progress flag */
GlobusTimeAbstimeGetCurrent(entry->abs_timeout);
globus_mutex_lock(&timer->mutex);
{
if(!timer->running ||
globus_reltime_cmp(&poll_time, &timer->minimal_delay) < 0)
{
GlobusTimeReltimeCopy(timer->minimal_delay, poll_time);
res = globus_callback_adjust_period(
timer->periodic_handle,
&timer->minimal_delay);
if(res != GLOBUS_SUCCESS)
{
globus_panic(GLOBUS_XIO_MODULE, res,
_XIOSL("globus_callback_adjust_period should always return success"
" in this case\n"
"timer @ 0x%x\n"
" globus_callback_adjust_period(%d, 0x%x);\n"),
timer->periodic_handle,
&timer->minimal_delay);
}
timer->running = GLOBUS_TRUE;
}
*entry->progress_ptr = GLOBUS_TRUE;
globus_list_insert(&timer->op_list, entry);
}
globus_mutex_unlock(&timer->mutex);
GlobusXIODebugInternalExit();
}
globus_bool_t
globus_i_xio_timer_unregister_timeout(
globus_i_xio_timer_t * timer,
void * datum)
{
globus_list_t * list;
globus_list_t * tmp_list = NULL;
globus_bool_t found = GLOBUS_FALSE;
/* intialize to remove warning, but not needed */
globus_i_xio_timer_entry_t * entry = NULL;
GlobusXIOName(globus_i_xio_timer_unregister_timeout);
GlobusXIODebugInternalEnter();
globus_mutex_lock(&timer->mutex);
{
for(list = timer->op_list;
!found && !globus_list_empty(list);
list = globus_list_rest(list))
{
entry = (globus_i_xio_timer_entry_t *) globus_list_first(list);
if(entry->datum == datum)
{
found = GLOBUS_TRUE;
tmp_list = list;
/* if the list is empty pause the callback */
}
}
if(found)
{
globus_list_remove(&timer->op_list, tmp_list);
globus_free(entry);
if(globus_list_empty(timer->op_list))
{
globus_callback_adjust_period(
timer->periodic_handle,
NULL);
timer->running = GLOBUS_FALSE;
}
}
}
globus_mutex_unlock(&timer->mutex);
GlobusXIODebugInternalExit();
return found;
}
void
globus_i_xio_timer_poller_callback(
void * user_arg)
{
globus_i_xio_timer_t * timer;
globus_list_t * list;
globus_abstime_t now;
globus_i_xio_timer_entry_t * entry;
globus_list_t * call_list = NULL;
globus_list_t * tmp_list = NULL;
GlobusXIOName(globus_i_xio_timer_poller_callback);
GlobusXIODebugInternalEnter();
timer = (globus_i_xio_timer_t *)user_arg;
GlobusTimeAbstimeGetCurrent(now);
globus_mutex_lock(&timer->mutex);
{
tmp_list = globus_list_copy(timer->op_list);
for(list = tmp_list;
!globus_list_empty(list);
list = globus_list_rest(list))
{
entry = (globus_i_xio_timer_entry_t *) globus_list_first(list);
/* time has expired */
if(globus_abstime_cmp(&now, &entry->abs_timeout) >= 0)
{
/* if progress was made up the expiration point and flip
* the progress flag
*/
if(*entry->progress_ptr)
{
*entry->progress_ptr = GLOBUS_FALSE;
}
/* timeout */
else
{
globus_list_insert(&call_list, entry);
globus_list_remove(&timer->op_list,
globus_list_search(timer->op_list, entry));
}
GlobusTimeAbstimeCopy(entry->abs_timeout, now);
GlobusTimeAbstimeInc(
entry->abs_timeout, entry->rel_timeout);
}
}
}
globus_mutex_unlock(&timer->mutex);
globus_list_free(tmp_list);
/* remove from the list all that were canceled */
while(!globus_list_empty(call_list))
{
entry = (globus_i_xio_timer_entry_t *)globus_list_remove(
&call_list, call_list);
/*
* call the users function
* if they return false then add the operation back into
* the pool list.
*/
if(!entry->timer_cb(entry->datum))
{
globus_mutex_lock(&timer->mutex);
{
globus_list_insert(&timer->op_list, entry);
}
globus_mutex_unlock(&timer->mutex);
}
/* if they return true we are done with the entry */
else
{
globus_free(entry);
}
}
GlobusXIODebugInternalExit();
}
globus_xio-6.6/PaxHeaders.22691/globus_xio_server.c 0000644 0000000 0000000 00000000132 14243161125 020442 x ustar 00 0000000 0000000 30 mtime=1653400149.724966412
30 atime=1653401489.018567776
30 ctime=1653403998.752961494
globus_xio-6.6/globus_xio_server.c 0000664 0001750 0001750 00000171424 14243161125 020613 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "globus_xio.h"
#include "globus_i_xio.h"
#include
/*
* note:
*
* Cancel Process
* --------------
* The only exception to when the accept can finish before the callback occurs
* is when a cancel happens. In the case the driver should stop what it is
* doing and finish with a canceled error. All drivers above it will get
* this error and should finish in the same manner, by cleaning up resources
* involved with this accpet and the calling finish with the cancel error.
* Once the error reaches the top xio will find all drivers were not notified
* of the cancel and ask them to destroy their links.
*
* Errors
* ------
* There are two times when an error can happens. The first is in the
* callback. The process for dealing with this is exctly as a canceled
* accept... The top callback comes back with an error and all successfully
* created driver links are destroyed.
*
* The second case is if the Pass fails. Once a driver calls pass it must
* only return the error code that pass returns. If that error code is
* GLOBUS_SUCESS then the driver should expect a callback, if it is not
* the driver will not receive the callback for which it registered. This
* rule allows the framework to know that if it receives an error from
* pass at the top level that no driver has an outstanding callback.
*
*/
#define GlobusIXIOServerDec(free, _in_s) \
do \
{ \
globus_i_xio_server_t * _s; \
\
_s = (_in_s); \
_s->ref--; \
if(_s->ref == 0) \
{ \
/* if the handle ref gets down to zero we must be in one \
* of the followninf staes. The statement is that the handle \
* only goes away when it is closed or a open fails \
*/ \
globus_assert(_s->state == GLOBUS_XIO_SERVER_STATE_CLOSED); \
free = GLOBUS_TRUE; \
} \
else \
{ \
free = GLOBUS_FALSE; \
} \
} while (0)
globus_list_t * globus_i_xio_outstanding_servers_list;
/**************************************************************************
* Internal functions
* ------------------
*************************************************************************/
static
globus_result_t
globus_l_xio_close_server(
globus_i_xio_server_t * xio_server);
static
void
globus_l_xio_server_destroy(
globus_i_xio_server_t * xio_server)
{
GlobusXIOName(globus_l_xio_server_destroy);
GlobusXIODebugInternalEnter();
globus_mutex_lock(&globus_i_xio_mutex);
{
globus_mutex_lock(&xio_server->mutex);
{
if(xio_server->sd_monitor != NULL)
{
GlobusXIODebugPrintf(
GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("[globus_i_xio_handle_destroy]"
" :: signalling handle unload.\n")));
xio_server->sd_monitor->count--;
if(xio_server->sd_monitor->count == 0)
{
globus_cond_signal(&globus_i_xio_cond);
}
}
else
{
globus_list_remove(
&globus_i_xio_outstanding_servers_list,
globus_list_search(
globus_i_xio_outstanding_servers_list, xio_server));
}
}
globus_mutex_unlock(&xio_server->mutex);
}
globus_mutex_unlock(&globus_i_xio_mutex);
globus_callback_space_destroy(xio_server->space);
globus_mutex_destroy(&xio_server->mutex);
if(xio_server->contact_string)
{
globus_free(xio_server->contact_string);
}
globus_free(xio_server);
GlobusXIODebugInternalExit();
}
static
void
globus_i_xio_server_post_accept(
globus_i_xio_op_t * xio_op);
static
void
globus_i_xio_server_will_block_cb(
globus_thread_callback_index_t wb_ndx,
globus_callback_space_t space,
void * user_args)
{
globus_i_xio_op_t * xio_op;
GlobusXIOName(globus_i_xio_server_will_block_cb);
GlobusXIODebugInternalEnter();
xio_op = (globus_i_xio_op_t *) user_args;
xio_op->restarted = GLOBUS_TRUE;
GlobusXIOOpInc(xio_op);
globus_thread_blocking_callback_disable(&wb_ndx);
globus_i_xio_server_post_accept(xio_op);
GlobusXIODebugInternalExit();
}
static
globus_result_t
globus_l_xio_server_handle_create(
globus_xio_handle_t * handle,
globus_xio_server_t server)
{
globus_i_xio_handle_t * ihandle;
globus_i_xio_context_t * context;
int ndx;
globus_result_t res = GLOBUS_SUCCESS;
GlobusXIOName(globus_l_xio_server_handle_create);
GlobusXIODebugInternalEnter();
if(handle == NULL)
{
res = GlobusXIOErrorParameter("handle");
goto error_context;
}
/* allocate and initialize context */
context = globus_i_xio_context_create(server->stack_size);
if(context == NULL)
{
res = GlobusXIOErrorMemory("context");
goto error_context;
}
/* allocate and intialize the handle structure */
ihandle = (globus_i_xio_handle_t *)
globus_calloc(1, sizeof(globus_i_xio_handle_t));
if(ihandle == NULL)
{
res = GlobusXIOErrorMemory("ihandle");
goto error_handle;
}
/* initialize the handle */
ihandle->ref = 1; /* itself */
ihandle->context = context;
ihandle->state = GLOBUS_XIO_HANDLE_STATE_ACCEPTED;
ihandle->space = GLOBUS_CALLBACK_GLOBAL_SPACE;
for(ndx = 0; ndx < server->stack_size; ndx++)
{
context->entry[ndx].driver = server->entry[ndx].driver;
}
*handle = ihandle;
GlobusXIODebugInternalExit();
return GLOBUS_SUCCESS;
error_handle:
globus_i_xio_context_destroy(context);
error_context:
GlobusXIODebugInternalExitWithError();
return res;
}
/*
* this is the only mechanism for delivering a callback to the user
*/
void
globus_l_xio_server_accept_kickout(
void * user_arg)
{
int ctr;
int wb_ndx;
globus_i_xio_server_t * xio_server;
globus_i_xio_op_t * xio_op;
globus_xio_handle_t accepted_handle = NULL;
globus_result_t res;
globus_bool_t destroy_server = GLOBUS_FALSE;
GlobusXIOName(globus_l_xio_server_accept_kickout);
GlobusXIODebugInternalEnter();
xio_op = (globus_i_xio_op_t *) user_arg;
xio_server = xio_op->_op_server;
/* create the structure if successful, otherwise the handle is null */
res = GlobusXIOObjToResult(xio_op->cached_obj);
if(res == GLOBUS_SUCCESS)
{
res = globus_l_xio_server_handle_create(&accepted_handle, xio_server);
if(res == GLOBUS_SUCCESS)
{
/* stick the link in the new handle's context */
for(ctr = 0; ctr < xio_op->stack_size; ctr++)
{
accepted_handle->context->entry[ctr].driver_handle =
xio_op->entry[ctr].link;
}
globus_mutex_lock(&globus_i_xio_mutex);
{
globus_list_insert(
&globus_i_xio_outstanding_handles_list, accepted_handle);
}
globus_mutex_unlock(&globus_i_xio_mutex);
}
}
/* if failed clean up the operation */
if(res != GLOBUS_SUCCESS)
{
for(ctr = 0; ctr < xio_op->stack_size; ctr++)
{
if(xio_op->entry[ctr].link != NULL)
{
globus_assert(
xio_server->entry[ctr].driver->link_destroy_func != NULL
&& "If the driver link is non-NULL the link_destroy_func must be defined");
/* ignore result code. user should be more interested in
result from callback */
xio_server->entry[ctr].driver->link_destroy_func(
xio_op->entry[ctr].link);
}
}
}
globus_thread_blocking_space_callback_push(
globus_i_xio_server_will_block_cb,
(void *) xio_op,
xio_op->blocking ? GLOBUS_CALLBACK_GLOBAL_SPACE: xio_server->space,
&wb_ndx);
/* call the users callback */
xio_op->_op_accept_cb(
xio_server,
accepted_handle,
res,
xio_op->user_arg);
globus_thread_blocking_callback_pop(&wb_ndx);
if(xio_op->restarted)
{
globus_mutex_lock(&xio_server->mutex);
{
GlobusXIOOpDec(xio_op);
if(xio_op->ref == 0)
{
/* remove the reference for the op on the server */
GlobusIXIOServerDec(destroy_server, xio_server);
globus_free(xio_op);
}
}
globus_mutex_unlock(&xio_server->mutex);
if(destroy_server)
{
globus_l_xio_server_destroy(xio_server);
}
return;
}
globus_i_xio_server_post_accept(xio_op);
GlobusXIODebugInternalExit();
}
void
globus_i_xio_server_post_accept(
globus_i_xio_op_t * xio_op)
{
globus_bool_t destroy_server = GLOBUS_FALSE;
globus_i_xio_server_t * xio_server;
GlobusXIOName(globus_i_xio_server_post_accept);
GlobusXIODebugInternalEnter();
xio_server = xio_op->_op_server;
/* if user called register accept in the callback we will be back from
the completeing state and into the accepting state */
/* lock up and do some clean up */
globus_mutex_lock(&xio_server->mutex);
{
globus_assert(xio_op->state == GLOBUS_XIO_OP_STATE_FINISH_WAITING);
xio_server->outstanding_operations--;
switch(xio_server->state)
{
case GLOBUS_XIO_SERVER_STATE_COMPLETING:
xio_server->op = NULL;
xio_server->state = GLOBUS_XIO_SERVER_STATE_OPEN;
break;
case GLOBUS_XIO_SERVER_STATE_CLOSE_PENDING:
if(xio_server->outstanding_operations == 0)
{
xio_server->state = GLOBUS_XIO_SERVER_STATE_CLOSING;
globus_l_xio_close_server(xio_server);
}
break;
case GLOBUS_XIO_SERVER_STATE_CLOSED:
case GLOBUS_XIO_SERVER_STATE_CLOSING:
xio_server->op = NULL;
break;
/* This can happen if when the callback is called the user
registers another accept and that accept callback is
called before the first callback returns. */
case GLOBUS_XIO_SERVER_STATE_OPEN:
break;
case GLOBUS_XIO_SERVER_STATE_ACCEPTING:
break;
default:
globus_assert(0 && "Unexpected state after accept callback");
break;
}
/* decrement reference for the callback if timeout has happened or
isn't registered this will go to zero */
GlobusXIOOpDec(xio_op);
if(xio_op->ref == 0)
{
GlobusIXIOServerDec(destroy_server, xio_server);
globus_free(xio_op);
}
}
globus_mutex_unlock(&xio_server->mutex);
if(destroy_server)
{
globus_l_xio_server_destroy(xio_server);
}
GlobusXIODebugInternalExit();
}
/*
* internal top level accept callback
*/
void
globus_i_xio_server_accept_callback(
globus_xio_operation_t op,
globus_result_t result,
void * user_arg)
{
globus_i_xio_server_t * xio_server;
globus_i_xio_op_t * xio_op;
globus_bool_t accept = GLOBUS_TRUE;
GlobusXIOName(globus_i_xio_server_accept_callback);
GlobusXIODebugInternalEnter();
xio_op = op;
xio_server = xio_op->_op_server;
globus_mutex_lock(&xio_server->mutex);
{
/* if in this state it means that the user either has or is about to
get a cancel callback. we must delay the delivery of this
callback until that returns */
xio_op->cached_obj = GlobusXIOResultToObj(result);
if(xio_op->state == GLOBUS_XIO_OP_STATE_TIMEOUT_PENDING)
{
accept = GLOBUS_FALSE;
}
else
{
/* if there is an outstanding accept callback */
if(xio_op->_op_server_timeout_cb != NULL)
{
if(globus_i_xio_timer_unregister_timeout(
&globus_i_xio_timeout_timer, xio_op))
{
GlobusXIOOpDec(xio_op);
globus_assert(xio_op->ref > 0);
}
}
}
xio_op->state = GLOBUS_XIO_OP_STATE_FINISH_WAITING;
switch(xio_server->state)
{
case GLOBUS_XIO_SERVER_STATE_ACCEPTING:
xio_server->state = GLOBUS_XIO_SERVER_STATE_COMPLETING;
break;
/* nothing to do for this case */
case GLOBUS_XIO_SERVER_STATE_CLOSE_PENDING:
break;
default:
globus_assert(0);
}
}
globus_mutex_unlock(&xio_server->mutex);
/* we may be delaying the callback until cancel returns */
if(accept)
{
globus_l_xio_server_accept_kickout((void *)xio_op);
}
GlobusXIODebugInternalExit();
}
static
globus_bool_t
globus_l_xio_accept_timeout_callback(
void * user_arg)
{
globus_i_xio_op_t * xio_op;
globus_i_xio_server_t * xio_server;
globus_bool_t rc;
globus_bool_t cancel;
globus_bool_t accept = GLOBUS_FALSE;
globus_bool_t timeout = GLOBUS_FALSE;
globus_bool_t destroy_server = GLOBUS_FALSE;
globus_callback_space_t space =
GLOBUS_CALLBACK_GLOBAL_SPACE;
GlobusXIOName(globus_l_xio_accept_timeout_callback);
GlobusXIODebugInternalEnter();
xio_op = (globus_i_xio_op_t *) user_arg;
xio_server = xio_op->_op_server;
globus_mutex_lock(&xio_server->mutex);
{
switch(xio_op->state)
{
/*
* this case happens when a serverwas successfully created but
* we were unable to unregister the callback and when the first
* pass fails and we are unable to cancel the timeout callback
*/
case GLOBUS_XIO_OP_STATE_FINISHED:
case GLOBUS_XIO_OP_STATE_FINISH_WAITING:
/* decerement the reference for the timeout callback */
GlobusXIOOpDec(xio_op);
if(xio_op->ref == 0)
{
/* remove the reference for the op on the server */
GlobusIXIOServerDec(destroy_server, xio_server);
globus_free(xio_op);
}
/* remove it from the timeout list */
rc = GLOBUS_TRUE;
break;
/* this case happens when we actually want to cancel the operation
The timeout code should insure that prograess is false if this
gets called in this state */
case GLOBUS_XIO_OP_STATE_OPERATING:
/* it is up to the timeout callback to set this to true */
rc = GLOBUS_FALSE;
/* cancel the sucker */
globus_assert(xio_op->_op_server_timeout_cb != NULL);
if(!xio_op->block_timeout)
{
timeout = GLOBUS_TRUE;
/* we don't need to cache the server object in local stack
because state insures that it will not go away */
/* put in canceling state to delay the accept callback */
xio_op->state = GLOBUS_XIO_OP_STATE_TIMEOUT_PENDING;
}
break;
/* fail on any ohter case */
default:
globus_assert(0);
}
}
globus_mutex_unlock(&xio_server->mutex);
/* if in cancel state, verfiy with user that they want to cancel */
if(timeout)
{
cancel = xio_op->_op_server_timeout_cb(
xio_server, xio_op->type);
}
/* all non time out casses can just return */
else
{
if(destroy_server)
{
globus_l_xio_server_destroy(xio_server);
}
goto exit;
}
globus_mutex_lock(&xio_server->mutex);
{
/* if canceling set the res and we will remove this timer event */
if(cancel)
{
rc = GLOBUS_TRUE;
/* Assume all timeouts originate from user */
xio_op->canceled = 1;
if(xio_op->cancel_cb)
{
globus_i_xio_op_entry_t * my_op;
my_op = &xio_op->entry[xio_op->ndx - 1];
my_op->in_register = GLOBUS_TRUE;
xio_op->cancel_cb(
xio_op, xio_op->cancel_arg, GLOBUS_XIO_ERROR_TIMEOUT);
my_op->in_register = GLOBUS_FALSE;
}
}
/* if an accept callback has already arriverd set flag to later
call accept callback and set rc to remove timed event */
if(xio_op->state == GLOBUS_XIO_OP_STATE_FINISH_WAITING)
{
accept = GLOBUS_TRUE;
rc = GLOBUS_TRUE;
}
/* if no accept is waiting, set state back to operating */
else
{
xio_op->state = GLOBUS_XIO_OP_STATE_OPERATING;
}
/* if we are remvoing the timed event */
if(rc)
{
/* decremenet the op reference count and insist that it is
not zero yet */
xio_op->_op_handle_timeout_cb = NULL;
GlobusXIOOpDec(xio_op);
globus_assert(xio_op->ref > 0);
}
}
globus_mutex_unlock(&xio_server->mutex);
/* if the accpet was pending we must call it */
if(accept)
{
if(!xio_op->blocking)
{
space = xio_server->space;
}
if(space != GLOBUS_CALLBACK_GLOBAL_SPACE)
{
/* register a oneshot callback */
globus_i_xio_register_oneshot(
NULL,
globus_l_xio_server_accept_kickout,
(void *)xio_op,
space);
}
/* in all other cases we can just call callback */
else
{
globus_l_xio_server_accept_kickout((void *)xio_op);
}
}
exit:
GlobusXIODebugInternalExit();
return rc;
}
void
globus_l_xio_server_close_kickout(
void * user_arg)
{
globus_i_xio_server_t * xio_server;
globus_bool_t destroy_server = GLOBUS_FALSE;
GlobusXIOName(globus_l_xio_server_close_kickout);
GlobusXIODebugInternalEnter();
xio_server = (globus_i_xio_server_t *) user_arg;
if(xio_server->cb)
{
xio_server->cb(xio_server, xio_server->user_arg);
}
globus_mutex_lock(&xio_server->mutex);
{
xio_server->state = GLOBUS_XIO_SERVER_STATE_CLOSED;
/* dec reference count then free. this makes sure we don't
free while in a user callback */
GlobusIXIOServerDec(destroy_server, xio_server);
}
globus_mutex_unlock(&xio_server->mutex);
if(destroy_server)
{
globus_l_xio_server_destroy(xio_server);
}
GlobusXIODebugInternalExit();
}
/*
* this is called locked
*/
globus_result_t
globus_l_xio_close_server(
globus_i_xio_server_t * xio_server)
{
int ctr;
globus_result_t res = GLOBUS_SUCCESS;
globus_result_t tmp_res;
globus_callback_space_t space =
GLOBUS_CALLBACK_GLOBAL_SPACE;
GlobusXIOName(globus_l_xio_close_server);
GlobusXIODebugInternalEnter();
for(ctr = 0; ctr < xio_server->stack_size; ctr++)
{
if(xio_server->entry[ctr].driver->server_destroy_func != NULL)
{
/* possible to lose a driver res, but you know.. so what? */
tmp_res = xio_server->entry[ctr].driver->server_destroy_func(
xio_server->entry[ctr].server_handle);
if(tmp_res != GLOBUS_SUCCESS)
{
res = GlobusXIOErrorWrapFailed("server_destroy", tmp_res);
}
}
}
if(!xio_server->blocking)
{
space = xio_server->space;
}
globus_i_xio_register_oneshot(
NULL,
globus_l_xio_server_close_kickout,
(void *)xio_server,
space);
GlobusXIODebugInternalExit();
return res;
}
void
globus_l_xio_server_close_cb(
globus_xio_server_t server,
void * user_arg)
{
globus_i_xio_blocking_t * info;
info = (globus_i_xio_blocking_t *) user_arg;
globus_mutex_lock(&info->mutex);
{
info->done = GLOBUS_TRUE;
globus_cond_signal(&info->cond);
}
globus_mutex_unlock(&info->mutex);
}
void
globus_l_server_accept_cb(
globus_xio_server_t server,
globus_xio_handle_t handle,
globus_result_t result,
void * user_arg)
{
globus_i_xio_blocking_t * info;
GlobusXIOName(globus_l_xio_server_register_accept);
GlobusXIODebugInternalEnter();
info = (globus_i_xio_blocking_t *) user_arg;
globus_mutex_lock(&info->mutex);
{
info->error_obj = GlobusXIOResultToObj(result);
info->accepted_handle = handle;
info->done = GLOBUS_TRUE;
globus_cond_signal(&info->cond);
}
globus_mutex_unlock(&info->mutex);
GlobusXIODebugInternalExit();
}
globus_result_t
globus_l_xio_server_register_accept(
globus_i_xio_op_t * xio_op)
{
globus_i_xio_server_t * xio_server;
globus_result_t res = GLOBUS_SUCCESS;
globus_bool_t free_server = GLOBUS_FALSE;
GlobusXIOName(globus_l_xio_server_register_accept);
GlobusXIODebugInternalEnter();
xio_server = xio_op->_op_server;
globus_mutex_lock(&xio_server->mutex);
{
if(xio_server->state != GLOBUS_XIO_SERVER_STATE_OPEN &&
xio_server->state != GLOBUS_XIO_SERVER_STATE_COMPLETING)
{
res = GlobusXIOErrorInvalidState(xio_server->state);
goto state_err;
}
xio_server->state = GLOBUS_XIO_SERVER_STATE_ACCEPTING;
xio_server->outstanding_operations++;
xio_op->type = GLOBUS_XIO_OPERATION_TYPE_ACCEPT;
xio_op->state = GLOBUS_XIO_OP_STATE_OPERATING;
xio_op->ref = 1;
xio_op->cancel_cb = NULL;
xio_op->canceled = 0;
xio_op->progress = GLOBUS_TRUE;
xio_op->_op_server_timeout_cb = xio_server->accept_timeout;
xio_op->ndx = 0;
xio_op->stack_size = xio_server->stack_size;
xio_op->entry[0].prev_ndx = -1;
xio_server->op = xio_op;
/*i deal with timeout if there is one */
if(xio_op->_op_server_timeout_cb != NULL)
{
GlobusXIOOpInc(xio_op);
globus_i_xio_timer_register_timeout(
&globus_i_xio_timeout_timer,
xio_op,
&xio_op->progress,
globus_l_xio_accept_timeout_callback,
&xio_server->accept_timeout_period);
}
/* add a reference to the server for the op */
xio_server->ref++;
}
globus_mutex_unlock(&xio_server->mutex);
/* add reference count for the pass. does not need to be done locked
since no one has op until it is passed */
GlobusXIOOpInc(xio_op);
res = globus_xio_driver_pass_accept(xio_op,
globus_i_xio_server_accept_callback, NULL);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
globus_mutex_lock(&xio_server->mutex);
{
GlobusXIOOpDec(xio_op);
if(xio_op->ref == 0)
{
GlobusIXIOServerDec(free_server, xio_server);
globus_assert(!free_server);
globus_free(xio_op);
}
}
globus_mutex_unlock(&xio_server->mutex);
GlobusXIODebugInternalExit();
return GLOBUS_SUCCESS;
err:
globus_mutex_lock(&xio_server->mutex);
{
GlobusXIOOpDec(xio_op); /* dec for the register */
globus_assert(xio_op->ref > 0);
/* set op to invalid type */
xio_op->state = GLOBUS_XIO_OP_STATE_FINISHED;
/* if a timeout was registered we must unregister it */
if(xio_op->_op_server_timeout_cb != NULL)
{
if(globus_i_xio_timer_unregister_timeout(
&globus_i_xio_timeout_timer, xio_op))
{
GlobusXIOOpDec(xio_op);
globus_assert(xio_op->ref > 0);
}
}
/* we dont dec the op here because its owned by the caller */
GlobusIXIOServerDec(free_server, xio_server);
globus_assert(!free_server);
}
state_err:
globus_mutex_unlock(&xio_server->mutex);
GlobusXIODebugInternalExitWithError();
return res;
}
/**************************************************************************
* API functions
* -------------
*************************************************************************/
/*
* initialize a server structure
*/
globus_result_t
globus_xio_server_create(
globus_xio_server_t * server,
globus_xio_attr_t server_attr,
globus_xio_stack_t stack)
{
globus_list_t * list;
globus_i_xio_server_t * xio_server = NULL;
globus_result_t res;
int ctr;
int stack_size;
void * ds_attr = NULL;
globus_i_xio_op_t * xio_op = NULL;
globus_xio_contact_t contact_info;
GlobusXIOName(globus_xio_server_create);
GlobusXIODebugEnter();
if(server == NULL)
{
res = GlobusXIOErrorParameter("server");
goto err_parm;
}
if(stack == NULL)
{
res = GlobusXIOErrorParameter("stack");
goto err_parm;
}
if(globus_list_empty(stack->driver_stack))
{
res = GlobusXIOErrorParameter("stack is empty");
goto err_parm;
}
/* take what the user stack has at the time of registration */
stack_size = globus_list_size(stack->driver_stack);
xio_op = (globus_i_xio_op_t *)
globus_calloc(1, sizeof(globus_i_xio_op_t) +
(sizeof(globus_i_xio_op_entry_t) * (stack_size - 1)));
if(xio_op == NULL)
{
res = GlobusXIOErrorMemory("operation");
goto err;
}
xio_server = (globus_i_xio_server_t *)
globus_calloc(1, sizeof(globus_i_xio_server_t) +
(sizeof(globus_i_xio_server_entry_t) * (stack_size - 1)));
if(xio_server == NULL)
{
res = GlobusXIOErrorMemory("server");
goto err;
}
xio_server->stack_size = globus_list_size(stack->driver_stack);
xio_server->ref = 1;
xio_server->state = GLOBUS_XIO_SERVER_STATE_OPEN;
xio_server->space = GLOBUS_CALLBACK_GLOBAL_SPACE;
globus_mutex_init(&xio_server->mutex, NULL);
xio_server->accept_timeout = NULL;
/* timeout handling */
if(server_attr != NULL)
{
if(server_attr->accept_timeout_cb)
{
xio_server->accept_timeout = server_attr->accept_timeout_cb;
GlobusTimeReltimeCopy(
xio_server->accept_timeout_period,
server_attr->accept_timeout_period);
}
xio_server->space = server_attr->space;
}
globus_callback_space_reference(xio_server->space);
/* Only using this op for its index, really... things like state
* don't matter to me. I will also be using the open_attr
* field for the server attr.
*/
xio_op->type = GLOBUS_XIO_OPERATION_TYPE_SERVER_INIT;
xio_op->_op_server = xio_server;
xio_op->stack_size = xio_server->stack_size;
/* walk through the stack and add each entry to the array */
ctr = 0;
for(list = stack->driver_stack;
!globus_list_empty(list);
list = globus_list_rest(list))
{
xio_server->entry[ctr].driver = (globus_xio_driver_t)
globus_list_first(list);
if(server_attr != NULL)
{
GlobusIXIOAttrGetDS(ds_attr, server_attr, \
xio_server->entry[ctr].driver);
xio_op->entry[ctr].open_attr = ds_attr;
}
ctr++;
}
for (xio_op->ndx = 0; xio_op->ndx < xio_op->stack_size; xio_op->ndx++)
{
globus_i_xio_driver_t * dp = xio_op->_op_server->entry[xio_op->ndx].driver;
if (dp->server_pre_init_func)
{
res = dp->server_pre_init_func(
xio_op->entry[xio_op->ndx].open_attr, NULL, xio_op);
if (res != GLOBUS_SUCCESS)
{
goto err;
}
}
}
memset(&contact_info, 0, sizeof(contact_info));
res = globus_xio_driver_pass_server_init(xio_op, &contact_info, NULL);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
globus_free(xio_op);
globus_mutex_lock(&globus_i_xio_mutex);
{
globus_list_insert(&globus_i_xio_outstanding_servers_list, xio_server);
}
globus_mutex_unlock(&globus_i_xio_mutex);
*server = xio_server;
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
if(xio_op)
{
globus_free(xio_op);
}
if(xio_server)
{
globus_mutex_destroy(&xio_server->mutex);
globus_callback_space_destroy(xio_server->space);
globus_free(xio_server);
}
*server = NULL;
err_parm:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_server_get_contact_string(
globus_xio_server_t server,
char ** contact_string)
{
globus_result_t res;
GlobusXIOName(globus_xio_server_get_contact_string);
GlobusXIODebugEnter();
if(contact_string == NULL)
{
res = GlobusXIOErrorParameter("contact_string");
goto err;
}
*contact_string = NULL;
if(server == NULL)
{
res = GlobusXIOErrorParameter("server");
goto err;
}
if(server->contact_string)
{
*contact_string = globus_libc_strdup(server->contact_string);
if(!*contact_string)
{
res = GlobusXIOErrorMemory("contact_string");
goto err;
}
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
/*
*
*/
globus_result_t
globus_xio_server_cntl(
globus_xio_server_t server,
globus_xio_driver_t driver,
int cmd,
...)
{
globus_bool_t found = GLOBUS_FALSE;
int ctr;
globus_result_t res = GLOBUS_SUCCESS;
va_list ap;
globus_i_xio_server_t * xio_server;
GlobusXIOName(globus_xio_server_cntl);
GlobusXIODebugEnter();
if(server == NULL)
{
res = GlobusXIOErrorParameter("server");
goto err;
}
xio_server = (globus_i_xio_server_t *) server;
globus_mutex_lock(&xio_server->mutex);
{
if(driver == NULL)
{
/* do general things */
}
else
{
for(ctr = 0;
!found && ctr < xio_server->stack_size;
ctr++)
{
if(xio_server->entry[ctr].driver == driver)
{
found = GLOBUS_TRUE;
va_start(ap, cmd);
res = xio_server->entry[ctr].driver->server_cntl_func(
xio_server->entry[ctr].server_handle,
cmd,
ap);
va_end(ap);
}
}
if(!found)
{
res = GlobusXIOErrorInvalidDriver(_XIOSL("not found"));
}
}
}
globus_mutex_unlock(&xio_server->mutex);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
/*
* register an accept
*/
globus_result_t
globus_xio_server_register_accept(
globus_xio_server_t server,
globus_xio_accept_callback_t cb,
void * user_arg)
{
int tmp_size;
globus_result_t res = GLOBUS_SUCCESS;
globus_i_xio_server_t * xio_server;
globus_i_xio_op_t * xio_op = NULL;
GlobusXIOName(globus_xio_server_register_accept);
GlobusXIODebugEnter();
if(server == NULL)
{
return GlobusXIOErrorParameter("server");
}
xio_server = (globus_i_xio_server_t *) server;
tmp_size = sizeof(globus_i_xio_op_t) +
(sizeof(globus_i_xio_op_entry_t) *
(xio_server->stack_size - 1));
xio_op = (globus_i_xio_op_t *) globus_malloc(tmp_size);
if(xio_op == NULL)
{
res = GlobusXIOErrorMemory("operation");
goto err;
}
memset(xio_op, '\0', tmp_size);
xio_op->_op_accept_cb = cb;
xio_op->user_arg = user_arg;
xio_op->_op_server = xio_server;
xio_op->stack_size = xio_server->stack_size;
res = globus_l_xio_server_register_accept(xio_op);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
if(xio_op != NULL)
{
globus_free(xio_op);
}
GlobusXIODebugExitWithError();
return res;
}
/*
* cancel the server
*/
globus_result_t
globus_xio_server_cancel_accept(
globus_xio_server_t server)
{
globus_result_t res = GLOBUS_SUCCESS;
globus_i_xio_server_t * xio_server;
GlobusXIOName(globus_xio_server_cancel_accept);
GlobusXIODebugEnter();
xio_server = (globus_i_xio_server_t *) server;
globus_mutex_lock(&xio_server->mutex);
{
if(xio_server->state != GLOBUS_XIO_SERVER_STATE_ACCEPTING &&
xio_server->state != GLOBUS_XIO_SERVER_STATE_COMPLETING)
{
res = GlobusXIOErrorInvalidState(xio_server->state);
}
else if(xio_server->op->canceled)
{
res = GlobusXIOErrorCanceled();
}
else
{
/* the callback is called locked. within it the driver is
allowed limited functionality. by calling this locked
can more efficiently pass the operation down the stack */
/* Cancel originates from user */
xio_server->op->canceled = 1;
if(xio_server->op->cancel_cb)
{
globus_i_xio_op_entry_t * my_op;
my_op = &xio_server->op->entry[xio_server->op->ndx - 1];
my_op->in_register = GLOBUS_TRUE;
xio_server->op->cancel_cb(xio_server->op,
xio_server->op->cancel_arg, GLOBUS_XIO_ERROR_CANCELED);
my_op->in_register = GLOBUS_FALSE;
}
}
}
globus_mutex_unlock(&xio_server->mutex);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
globus_result_t
globus_xio_server_accept(
globus_xio_handle_t * out_handle,
globus_xio_server_t server)
{
int tmp_size;
globus_result_t res = GLOBUS_SUCCESS;
globus_i_xio_server_t * xio_server;
globus_i_xio_op_t * xio_op;
globus_i_xio_blocking_t * info;
GlobusXIOName(globus_xio_server_accept);
GlobusXIODebugEnter();
if(out_handle == NULL)
{
res = GlobusXIOErrorParameter("out_handle");
goto err;
}
*out_handle = NULL;
if(server == NULL)
{
res = GlobusXIOErrorParameter("server");
goto err;
}
xio_server = (globus_i_xio_server_t *) server;
tmp_size = sizeof(globus_i_xio_op_t) +
(sizeof(globus_i_xio_op_entry_t) *
(xio_server->stack_size - 1));
xio_op = (globus_i_xio_op_t *) globus_malloc(tmp_size);
if(xio_op == NULL)
{
res = GlobusXIOErrorMemory("operation");
goto err;
}
memset(xio_op, '\0', tmp_size);
info = globus_i_xio_blocking_alloc();
if(info == NULL)
{
res = GlobusXIOErrorMemory("internal strucature");
goto info_alloc_err;
}
xio_op->_op_accept_cb = globus_l_server_accept_cb;
xio_op->user_arg = info;
xio_op->_op_server = xio_server;
xio_op->stack_size = xio_server->stack_size;
xio_op->blocking = GLOBUS_TRUE;
GlobusXIOCurrentBlockedThread(xio_op->blocked_thread);
res = globus_l_xio_server_register_accept(xio_op);
if(res != GLOBUS_SUCCESS)
{
goto register_error;
}
globus_mutex_lock(&info->mutex);
{
while(!info->done)
{
globus_cond_wait(&info->cond, &info->mutex);
}
}
globus_mutex_unlock(&info->mutex);
if(info->error_obj != NULL)
{
res = GlobusXIOObjToResult(info->error_obj);
globus_i_xio_blocking_destroy(info);
goto err;
}
*out_handle = info->accepted_handle;
globus_i_xio_blocking_destroy(info);
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
register_error:
globus_i_xio_blocking_destroy(info);
info_alloc_err:
globus_free(xio_op);
err:
GlobusXIODebugExitWithError();
return res;
}
/* called locked */
globus_result_t
globus_i_xio_server_close(
globus_xio_server_t xio_server,
globus_xio_server_callback_t cb,
void * user_arg)
{
globus_result_t res = GLOBUS_SUCCESS;
GlobusXIOName(globus_i_xio_server_close);
GlobusXIODebugInternalEnter();
if(xio_server->state == GLOBUS_XIO_SERVER_STATE_CLOSE_PENDING ||
xio_server->state == GLOBUS_XIO_SERVER_STATE_CLOSING ||
xio_server->state == GLOBUS_XIO_SERVER_STATE_CLOSED)
{
res = GlobusXIOErrorInvalidState(xio_server->state);
}
else
{
/* the callback is called locked. within it the driver is
allowed limited functionality. by calling this locked
can more efficiently pass the operation down the stack */
if(xio_server->op != NULL)
{
/* cancel originates from user */
xio_server->op->canceled = 1;
if(xio_server->op->cancel_cb)
{
globus_i_xio_op_entry_t * my_op;
my_op = &xio_server->op->entry[xio_server->op->ndx - 1];
my_op->in_register = GLOBUS_TRUE;
xio_server->op->cancel_cb(xio_server->op,
xio_server->op->cancel_arg, GLOBUS_XIO_ERROR_CANCELED);
my_op->in_register = GLOBUS_FALSE;
}
}
xio_server->cb = cb;
xio_server->user_arg = user_arg;
switch(xio_server->state)
{
case GLOBUS_XIO_SERVER_STATE_ACCEPTING:
case GLOBUS_XIO_SERVER_STATE_COMPLETING:
xio_server->state = GLOBUS_XIO_SERVER_STATE_CLOSE_PENDING;
break;
case GLOBUS_XIO_SERVER_STATE_OPEN:
xio_server->state = GLOBUS_XIO_SERVER_STATE_CLOSING;
globus_l_xio_close_server(xio_server);
break;
default:
globus_assert(0);
}
}
GlobusXIODebugInternalExit();
return res;
}
/*
* destroy the server
*/
globus_result_t
globus_xio_server_register_close(
globus_xio_server_t server,
globus_xio_server_callback_t cb,
void * user_arg)
{
globus_i_xio_server_t * xio_server;
globus_result_t res = GLOBUS_SUCCESS;
GlobusXIOName(globus_xio_server_register_close);
GlobusXIODebugEnter();
if(server == NULL)
{
res = GlobusXIOErrorParameter("server");
goto err;
}
xio_server = (globus_i_xio_server_t *) server;
globus_mutex_lock(&xio_server->mutex);
{
if(xio_server->sd_monitor != NULL)
{
res = GlobusXIOErrorUnloaded();
}
else
{
res = globus_i_xio_server_close(xio_server, cb, user_arg);
}
}
globus_mutex_unlock(&xio_server->mutex);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
/*
* destroy the server
*/
globus_result_t
globus_xio_server_close(
globus_xio_server_t server)
{
globus_i_xio_server_t * xio_server;
globus_result_t res = GLOBUS_SUCCESS;
globus_i_xio_blocking_t * info;
GlobusXIOName(globus_xio_server_close);
GlobusXIODebugEnter();
if(server == NULL)
{
res = GlobusXIOErrorParameter("server");
goto err;
}
info = globus_i_xio_blocking_alloc();
if(info == GLOBUS_NULL)
{
res = GlobusXIOErrorMemory("internal");
goto err;
}
xio_server = (globus_i_xio_server_t *) server;
globus_mutex_lock(&info->mutex);
{
xio_server->blocking = GLOBUS_TRUE;
res = globus_xio_server_register_close(xio_server,
globus_l_xio_server_close_cb, info);
if(res == GLOBUS_SUCCESS)
{
while(!info->done)
{
globus_cond_wait(&info->cond, &info->mutex);
}
}
}
globus_mutex_unlock(&info->mutex);
globus_i_xio_blocking_destroy(info);
if(res != GLOBUS_SUCCESS)
{
goto err;
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
err:
GlobusXIODebugExitWithError();
return res;
}
void
globus_xio_contact_destroy(
globus_xio_contact_t * contact_info)
{
GlobusXIOName(globus_xio_contact_destroy);
GlobusXIODebugInternalEnter();
if (contact_info)
{
free(contact_info->unparsed);
free(contact_info->resource);
free(contact_info->host);
free(contact_info->port);
free(contact_info->scheme);
free(contact_info->user);
free(contact_info->pass);
free(contact_info->subject);
}
GlobusXIODebugInternalExit();
}
static
void
globus_l_xio_decode_hex(
char * s)
{
char * d;
char t;
if(!s || !(s = strchr(s, '%')))
{
return;
}
d = s;
while(*s)
{
t = *s;
if(t == '%')
{
if(*(s + 1) == '%')
{
s++;
}
else if(isxdigit(*(s + 1)) && isxdigit(*(s + 2)))
{
char hexstring[3];
hexstring[0] = *(++s);
hexstring[1] = *(++s);
hexstring[2] = 0;
t = (char) strtol(hexstring, NULL, 16);
}
}
*d = t;
s++;
d++;
}
*d = 0;
}
/*
* if enc is NULL, no encoding will be done, string will just be duplicated.
* If it is non-NULL (but possibly empty) all characters in the
* string, the '%', and 01-1F and 7F-FF will be encoded with the %hh method.
*
* every string returned by this func must be freed
*/
static
char *
globus_l_xio_encode_hex(
const char * s,
const char * enc)
{
char * e;
char * encoded;
static char hexchars[] = "0123456789ABCDEF";
if(!s)
{
return NULL;
}
if(!enc)
{
return globus_libc_strdup(s);
}
encoded = (char *) globus_malloc((3 * strlen(s) + 1) * sizeof(char));
if(encoded)
{
e = encoded;
while(*s)
{
unsigned n = (unsigned) *s;
if(n <= 0x1F || n >= 0x7F || *s == '%' || (*enc && strchr(enc, n)))
{
*(e++) = '%';
*(e++) = hexchars[n >> 4];
*(e++) = hexchars[n & 15];
s++;
}
else
{
*(e++) = *(s++);
}
}
*e = 0;
}
return encoded;
}
/*
*
* -unparsed (up till end)
*
* if("://" before "/")
* -scheme (up till "://")
* if(^ "/")
* -path (up till end)
* else
* if("@" before "/" or "<")
* -user (up till ":" or "@")
* if(^ ":")
* -pass (up till "@")
* if(^ "<")
* -subject (up till ">:")
* if(^ "[")
* -host (up till "]")
* else
* -host (up till ":" or "/")
* if(^ ":")
* -port (up till "/")
* if(^ "/")
* -path (up till end)
* else
* if(^ "file:")
* -path (up till end)
* else if(":" before end and no invalid host chars)
* -host (up till ":")
* -port (up till end)
* else
* -path (up till end)
*
* XXX if its possible for plain filenames to contain a :, it really should be
* preceded with file:
*/
globus_result_t
globus_xio_contact_parse(
globus_xio_contact_t * contact_info,
const char * contact_string)
{
char * working;
char * save = NULL;
char * s;
char * p;
globus_bool_t decode = GLOBUS_TRUE;
globus_result_t result;
GlobusXIOName(globus_xio_contact_parse);
GlobusXIODebugInternalEnter();
memset(contact_info, 0, sizeof(globus_xio_contact_t));
if(contact_string && *contact_string)
{
contact_info->unparsed = globus_libc_strdup(contact_string);
if(!contact_info->unparsed)
{
goto error_alloc;
}
save = globus_libc_strdup(contact_string);
if(!save)
{
goto error_alloc;
}
working = save;
/* look for scheme */
for(s = working; *s && *s != ':' && *s != '/'; s++);
if(*s == ':' && *(s + 1) == '/' && *(s + 2) == '/')
{
*s = 0;
contact_info->scheme = globus_libc_strdup(working);
if(!contact_info->scheme)
{
goto error_alloc;
}
working = s + 3;
if(*working != '/')
{
/* look for user:pass */
for(s = working;
*s && *s != '@' && *s != '<' && *s != '/';
s++);
if(*s == '@')
{
p = s + 1;
*s = 0;
if((s = strchr(working, ':')))
{
*(s++) = 0;
if(*s)
{
contact_info->pass = globus_libc_strdup(s);
if(!contact_info->pass)
{
goto error_alloc;
}
}
}
if(*working)
{
contact_info->user = globus_libc_strdup(working);
if(!contact_info->user)
{
goto error_alloc;
}
}
working = p;
}
/* look for subject */
if(*working == '<')
{
working++;
s = strchr(working, '>');
if(!s)
{
result = GlobusXIOErrorContactString(_XIOSL("expecting >"));
goto error_format;
}
*s = 0;
if(*working)
{
contact_info->subject = globus_libc_strdup(working);
if(!contact_info->subject)
{
goto error_alloc;
}
}
working = s + 1;
if(*working == ':')
{
working++;
}
}
/* find host:port */
if(*working == '[')
{
working++;
s = strchr(working, ']');
if(!s)
{
result = GlobusXIOErrorContactString("expecting ]");
goto error_format;
}
*(s++) = 0;
}
else
{
for(s = working; *s && *s != ':' && *s != '/'; s++);
}
if(*s == ':')
{
*(s++) = 0;
if((p = strchr(s, '/')))
{
*p = 0;
}
if(*s)
{
contact_info->port = globus_libc_strdup(s);
if(!contact_info->port)
{
goto error_alloc;
}
}
if(p)
{
s = p + 1;
}
else
{
/* no path, just end it here */
*s = 0;
}
}
else if(*s == '/')
{
*(s++) = 0;
}
else if(*s)
{
result = GlobusXIOErrorContactString(_XIOSL("expecting : or /"));
goto error_format;
}
if(*working)
{
contact_info->host = globus_libc_strdup(working);
if(!contact_info->host)
{
goto error_alloc;
}
}
working = s;
}
else
{
working++;
}
/* copy path portion */
if(*working)
{
contact_info->resource = globus_libc_strdup(working);
if(!contact_info->resource)
{
goto error_alloc;
}
}
}
else
{
/* see if its file or host:port form */
if(strncmp(working, "file:", 5) == 0)
{
working += 5;
if(*working)
{
contact_info->resource = globus_libc_strdup(working);
if(!contact_info->resource)
{
goto error_alloc;
}
}
contact_info->scheme = globus_libc_strdup("file");
if(!contact_info->scheme)
{
goto error_alloc;
}
}
else if((s = strrchr(working, ':')) && !strpbrk(working, "\\/"))
{
*(s++) = 0;
if(*s)
{
contact_info->port = globus_libc_strdup(s);
if(!contact_info->port)
{
goto error_alloc;
}
}
if(*working == '[')
{
working++;
s = strchr(working, ']');
if(!s)
{
result = GlobusXIOErrorContactString(_XIOSL("expecting ]"));
goto error_format;
}
*s = 0;
}
if(*working)
{
contact_info->host = globus_libc_strdup(working);
if(!contact_info->host)
{
goto error_alloc;
}
}
}
else
{
decode = GLOBUS_FALSE;
contact_info->resource = globus_libc_strdup(working);
if(!contact_info->resource)
{
goto error_alloc;
}
contact_info->scheme = globus_libc_strdup("file");
if(!contact_info->scheme)
{
goto error_alloc;
}
}
}
/* don't decode anything that wasn't passed in as part of a url */
if(decode)
{
globus_l_xio_decode_hex(contact_info->resource);
globus_l_xio_decode_hex(contact_info->host);
globus_l_xio_decode_hex(contact_info->port);
globus_l_xio_decode_hex(contact_info->scheme);
globus_l_xio_decode_hex(contact_info->user);
globus_l_xio_decode_hex(contact_info->pass);
globus_l_xio_decode_hex(contact_info->subject);
}
/* XXX validate some of the fields */
globus_free(save);
}
GlobusXIODebugInternalExit();
return GLOBUS_SUCCESS;
error_alloc:
result = GlobusXIOErrorMemory("contact_info");
error_format:
if(save)
{
globus_free(save);
}
globus_xio_contact_destroy(contact_info);
GlobusXIODebugInternalExitWithError();
return result;
}
/* this is more than enough for the 7 possible fields now
* be sure to update this if it can get bigger
*/
#define GLOBUS_L_XIO_LAYOUT_SIZE 20
/*
* if an element within encode_chars is NULL, no encoding will be done for that
* element. If it is non-NULL (but possibly empty) all characters in the
* string, the '%', and 00-1F and 7F-FF will be encoded with the %hh method.
*/
globus_result_t
globus_xio_contact_info_to_encoded_string(
const globus_xio_contact_t * contact_info,
const globus_xio_contact_t * encode_chars,
char ** contact_string)
{
globus_bool_t path_only = GLOBUS_FALSE;
globus_bool_t host_port_only = GLOBUS_FALSE;
globus_xio_contact_t local_info;
const char * layout[GLOBUS_L_XIO_LAYOUT_SIZE];
int i = GLOBUS_L_XIO_LAYOUT_SIZE;
GlobusXIOName(globus_xio_contact_info_to_string);
GlobusXIODebugInternalEnter();
if(encode_chars)
{
memset(&local_info, 0, sizeof(local_info));
local_info.resource = globus_l_xio_encode_hex(
contact_info->resource, encode_chars->resource);
local_info.host = globus_l_xio_encode_hex(
contact_info->host, encode_chars->host);
local_info.port = globus_l_xio_encode_hex(
contact_info->port, encode_chars->port);
local_info.scheme = globus_l_xio_encode_hex(
contact_info->scheme, encode_chars->scheme);
local_info.user = globus_l_xio_encode_hex(
contact_info->user, encode_chars->user);
local_info.pass = globus_l_xio_encode_hex(
contact_info->pass, encode_chars->pass);
local_info.subject = globus_l_xio_encode_hex(
contact_info->subject, encode_chars->subject);
contact_info = &local_info;
}
if(contact_info->resource &&
!contact_info->scheme &&
!contact_info->host)
{
path_only = GLOBUS_TRUE;
}
if(contact_info->host && contact_info->port && !contact_info->scheme &&
!contact_info->resource && !contact_info->user &&
!contact_info->subject)
{
host_port_only = GLOBUS_TRUE;
}
if(contact_info->resource)
{
if(path_only)
{
layout[--i] = contact_info->resource;
}
else
{
if(*contact_info->resource == '/')
{
layout[--i] = contact_info->resource + 1;
layout[--i] = "/%2F";
}
else
{
layout[--i] = contact_info->resource;
layout[--i] = "/";
}
}
}
if(contact_info->host)
{
if(contact_info->port)
{
layout[--i] = contact_info->port;
layout[--i] = ":";
}
if(strchr(contact_info->host, ':'))
{
layout[--i] = "]";
layout[--i] = contact_info->host;
layout[--i] = "[";
}
else
{
layout[--i] = contact_info->host;
}
if(contact_info->subject)
{
layout[--i] = ">";
layout[--i] = contact_info->subject;
layout[--i] = "<";
}
if(contact_info->user)
{
layout[--i] = "@";
if(contact_info->pass)
{
layout[--i] = contact_info->pass;
layout[--i] = ":";
}
layout[--i] = contact_info->user;
}
}
if(contact_info->scheme)
{
layout[--i] = "://";
layout[--i] = contact_info->scheme;
}
else if(!path_only && !host_port_only)
{
layout[--i] = "xio://";
}
*contact_string = globus_libc_join(
&layout[i], GLOBUS_L_XIO_LAYOUT_SIZE - i);
if(encode_chars)
{
globus_xio_contact_destroy(&local_info);
}
GlobusXIODebugInternalExit();
return GLOBUS_SUCCESS;
}
globus_result_t
globus_xio_contact_info_to_string(
const globus_xio_contact_t * contact_info,
char ** contact_string)
{
return globus_xio_contact_info_to_encoded_string(
contact_info, NULL, contact_string);
}
globus_result_t
globus_xio_contact_info_to_url(
const globus_xio_contact_t * contact_info,
char ** contact_string)
{
globus_xio_contact_t encode_chars;
memset(&encode_chars, 0, sizeof(encode_chars));
encode_chars.resource = " \"#$&+,:;<=>?@[\\]^`{|}~!*";
encode_chars.user = "<> @:/\"'#";
encode_chars.pass = "<> @:/\"'#";
encode_chars.subject = "<> \"'#";
return globus_xio_contact_info_to_encoded_string(
contact_info, &encode_chars, contact_string);
}
globus_xio-6.6/PaxHeaders.22691/globus_xio_pass.c 0000644 0000000 0000000 00000000132 14243161125 020102 x ustar 00 0000000 0000000 30 mtime=1653400149.724966412
30 atime=1653401488.997567984
30 ctime=1653403998.754961475
globus_xio-6.6/globus_xio_pass.c 0000664 0001750 0001750 00000156664 14243161125 020264 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "globus_i_xio.h"
#include "globus_xio_util.h"
/************************************************************************
* open
* ----
***********************************************************************/
globus_result_t
globus_xio_driver_pass_open(
globus_xio_operation_t in_op,
const globus_xio_contact_t * contact_info,
globus_xio_driver_callback_t in_cb,
void * in_user_arg)
{
globus_i_xio_op_t * op;
globus_i_xio_handle_t * handle;
globus_i_xio_context_t * context;
globus_i_xio_context_entry_t * my_context;
globus_i_xio_op_entry_t * my_op;
int prev_ndx;
globus_result_t res;
globus_bool_t destroy_handle = GLOBUS_FALSE;
globus_bool_t close = GLOBUS_FALSE;
globus_xio_driver_t driver;
GlobusXIOName(globus_xio_driver_pass_open);
GlobusXIODebugInternalEnter();
op = (in_op);
globus_assert(op->ndx < op->stack_size);
handle = op->_op_handle;
context = op->_op_context;
op->progress = GLOBUS_TRUE;
op->block_timeout = GLOBUS_FALSE;
if(op->canceled)
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] :Operation canceled\n"), _xio_name));
res = GlobusXIOErrorCanceled();
}
else
{
my_context = &context->entry[op->ndx];
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_OPENING);
my_context->outstanding_operations++;
context->ref++;
prev_ndx = op->ndx;
do
{
driver = context->entry[op->ndx].driver;
op->ndx++;
}
while(driver->transport_open_func == NULL &&
driver->transform_open_func == NULL);
op->entry[prev_ndx].next_ndx = op->ndx;
op->entry[prev_ndx].type = GLOBUS_XIO_OPERATION_TYPE_OPEN;
my_op = &op->entry[op->ndx - 1];
my_op->cb = (in_cb);
my_op->user_arg = (in_user_arg);
my_op->prev_ndx = prev_ndx;
my_op->type = GLOBUS_XIO_OPERATION_TYPE_OPEN;
/* at time that stack is built this will be varified */
globus_assert(op->ndx <= context->stack_size);
/* ok to do this unlocked because no one else has it yet */
op->ref += 2; /* 1 for the pass, and one until finished */
my_op->in_register = GLOBUS_TRUE;
if(op->ndx == op->stack_size)
{
res = driver->transport_open_func(
contact_info,
my_op->link,
my_op->open_attr,
op);
}
else
{
res = driver->transform_open_func(
contact_info,
my_op->link,
my_op->open_attr,
op);
}
my_op->in_register = GLOBUS_FALSE;
if(driver->attr_destroy_func != NULL && my_op->open_attr != NULL)
{
driver->attr_destroy_func(my_op->open_attr);
my_op->open_attr = NULL;
}
if(res == GLOBUS_SUCCESS && prev_ndx == 0)
{
while(op->finished_delayed)
{
/* reuse this blocked thread to finish the operation */
op->finished_delayed = GLOBUS_FALSE;
globus_i_xio_driver_resume_op(op);
}
}
globus_mutex_lock(&context->mutex);
{
if(res != GLOBUS_SUCCESS)
{
globus_i_xio_pass_failed(op, my_context, &close,
&destroy_handle);
context->ref--;
/* cant possibly be 0 while there is still this op */
globus_assert(context->ref > 0);
globus_assert(!destroy_handle);
}
GlobusXIOOpDec(op); /* for the pass */
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
}
globus_mutex_unlock(&context->mutex);
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
}
GlobusXIODebugInternalExit();
return res;
}
void
globus_xio_driver_finished_open(
void * in_dh,
globus_xio_operation_t in_op,
globus_result_t in_res)
{
globus_i_xio_op_t * op;
globus_i_xio_context_entry_t * my_context;
globus_i_xio_context_t * context;
globus_i_xio_op_entry_t * my_op;
globus_result_t res;
globus_callback_space_t space =
GLOBUS_CALLBACK_GLOBAL_SPACE;
GlobusXIOName(globus_xio_driver_finished_open);
GlobusXIODebugInternalEnter();
res = (in_res);
op = (globus_i_xio_op_t *)(in_op);
globus_assert(op->ndx > 0);
op->progress = GLOBUS_TRUE;
op->block_timeout = GLOBUS_FALSE;
context = op->_op_context;
context->entry[op->ndx - 1].driver_handle = (in_dh);
my_op = &op->entry[op->ndx - 1];
my_context = &context->entry[my_op->prev_ndx];
/* no operation can happen while in OPENING state so no need to lock */
switch(my_context->state)
{
case GLOBUS_XIO_CONTEXT_STATE_OPENING:
if(res == GLOBUS_SUCCESS)
{
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_OPEN);
}
else
{
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_OPEN_FAILED);
}
break;
/* if user has already called close */
case GLOBUS_XIO_CONTEXT_STATE_OPENING_AND_CLOSING:
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_CLOSING);
break;
default:
globus_assert(0);
}
if(my_op->prev_ndx == 0 && !op->blocking && op->_op_handle)
{
space = op->_op_handle->space;
}
op->cached_obj = GlobusXIOResultToObj(res);
if(my_op->in_register || space != GLOBUS_CALLBACK_GLOBAL_SPACE)
{
/* if this is a blocking op, we avoid the oneshot by delaying the
* finish until the stack unwinds
*/
if(op->blocking &&
GlobusXIOBlockedThreadMatchesCurrentThread(op->blocked_thread))
{
GlobusXIODebugDelayedFinish();
op->finished_delayed = GLOBUS_TRUE;
}
else
{
GlobusXIODebugInregisterOneShot();
globus_i_xio_register_oneshot(
op->_op_handle,
globus_l_xio_driver_open_op_kickout,
(void *)op,
space);
}
}
else
{
globus_l_xio_driver_open_op_kickout(op);
}
GlobusXIODebugInternalExit();
}
void
globus_xio_driver_open_delivered(
globus_xio_operation_t in_op,
int in_ndx,
globus_xio_operation_type_t * deliver_type)
{
globus_i_xio_op_t * op;
globus_i_xio_op_t * close_op = NULL;
globus_i_xio_context_entry_t * my_context;
globus_i_xio_context_t * context;
globus_bool_t close_kickout = GLOBUS_FALSE;
globus_bool_t destroy_handle = GLOBUS_FALSE;
globus_bool_t destroy_context = GLOBUS_FALSE;
globus_i_xio_handle_t * handle;
globus_callback_space_t space =
GLOBUS_CALLBACK_GLOBAL_SPACE;
GlobusXIOName(globus_xio_driver_open_delivered);
GlobusXIODebugInternalEnter();
op = (in_op);
context = op->_op_context;
handle = op->_op_handle;
my_context = &context->entry[in_ndx];
/* LOCK */
globus_mutex_lock(&context->mutex);
{
/* make sure it only gets delivered once */
if(deliver_type == NULL ||
*deliver_type == GLOBUS_XIO_OPERATION_TYPE_FINISHED)
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] : Already delivered\n"), _xio_name));
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
globus_mutex_unlock(&context->mutex);
goto exit;
}
*deliver_type = GLOBUS_XIO_OPERATION_TYPE_FINISHED;
op->entry[in_ndx].deliver_type = NULL;
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
globus_assert(my_context->outstanding_operations > 0);
my_context->outstanding_operations--;
switch(my_context->state)
{
/* open failed and user didn't try and close */
case GLOBUS_XIO_CONTEXT_STATE_OPEN_FAILED:
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_CLOSED);
context->ref--;
break;
/* this happens when the open fails and the user calls close */
case GLOBUS_XIO_CONTEXT_STATE_OPENING_AND_CLOSING:
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_CLOSING);
if(!my_context->close_started &&
my_context->outstanding_operations == 0 &&
my_context->close_op != NULL)
{
close_kickout = GLOBUS_TRUE;
my_context->close_started = GLOBUS_TRUE;
close_op = my_context->close_op;
context->ref--;
}
break;
case GLOBUS_XIO_CONTEXT_STATE_OPEN:
case GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED:
case GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED:
case GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED_AND_CLOSING:
break;
case GLOBUS_XIO_CONTEXT_STATE_CLOSING:
case GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED_AND_CLOSING:
if(!my_context->close_started &&
my_context->outstanding_operations == 0 &&
my_context->close_op != NULL)
{
my_context->close_started = GLOBUS_TRUE;
close_op = my_context->close_op;
}
break;
default:
globus_assert(0);
break;
}
if(context->ref == 0)
{
destroy_context = GLOBUS_TRUE;
}
}
globus_mutex_unlock(&context->mutex);
if(close_op != NULL)
{
/* if closed before fully opened and open was successful we need
to start the regular close process */
if(!close_kickout)
{
globus_i_xio_driver_start_close(close_op, GLOBUS_FALSE);
}
/* if open failed then just kickout the close */
else
{
if(close_op->entry[close_op->ndx - 1].prev_ndx == 0 &&
!close_op->blocking &&
close_op->_op_handle != NULL)
{
space = close_op->_op_handle->space;
}
globus_i_xio_register_oneshot(
handle,
globus_l_xio_driver_op_close_kickout,
(void *)close_op,
space);
}
}
exit:
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
if(destroy_context)
{
/* the only way we'll be destroying the context is if this was a
* driver op and the handle no longer exists
*/
globus_assert(!destroy_handle);
globus_i_xio_context_destroy(context);
}
GlobusXIODebugInternalExit();
}
/************************************************************************
* close
* -----
***********************************************************************/
globus_result_t
globus_xio_driver_pass_close(
globus_xio_operation_t in_op,
globus_xio_driver_callback_t in_cb,
void * in_ua)
{
globus_i_xio_op_t * op;
globus_i_xio_context_t * context;
globus_i_xio_context_entry_t * my_context;
globus_bool_t pass;
globus_i_xio_op_entry_t * my_op;
int prev_ndx;
globus_result_t res = GLOBUS_SUCCESS;
globus_xio_driver_t driver;
globus_xio_operation_type_t deliver_type =
GLOBUS_XIO_OPERATION_TYPE_FINISHED;
GlobusXIOName(globus_xio_driver_pass_close);
GlobusXIODebugInternalEnter();
op = (in_op);
globus_assert(op->ndx < op->stack_size);
context = op->_op_context;
op->progress = GLOBUS_TRUE;
op->block_timeout = GLOBUS_FALSE;
my_context = &context->entry[op->ndx];
if(op->canceled && op->type != GLOBUS_XIO_OPERATION_TYPE_OPEN)
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] :Operation canceled\n"), _xio_name));
res = GlobusXIOErrorCanceled();
}
else
{
prev_ndx = op->ndx;
do
{
driver = context->entry[op->ndx].driver;
op->ndx++;
}
while(driver->close_func == NULL);
my_op = &op->entry[op->ndx - 1];
my_op->type = GLOBUS_XIO_OPERATION_TYPE_CLOSE;
/* deal with context state */
globus_mutex_lock(&context->mutex);
{
switch(my_context->state)
{
case GLOBUS_XIO_CONTEXT_STATE_OPEN:
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_CLOSING);
break;
case GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED:
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED_AND_CLOSING);
break;
case GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED:
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED_AND_CLOSING);
break;
case GLOBUS_XIO_CONTEXT_STATE_OPEN_FAILED:
case GLOBUS_XIO_CONTEXT_STATE_OPENING:
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_OPENING_AND_CLOSING);
break;
default:
globus_assert(0);
}
/* a barrier will never happen if the level above already did th
close barrier and this level has not created any driver ops.
in this case outstanding_operations is garentueed to be zero
*/
globus_assert(!my_context->close_started);
if(my_context->outstanding_operations == 0)
{
pass = GLOBUS_TRUE;
my_context->close_started = GLOBUS_TRUE;
}
/* cache the op for close barrier */
else
{
pass = GLOBUS_FALSE;
my_context->close_op = op;
}
if(op->entry[prev_ndx].deliver_type != NULL)
{
/* make local copy */
deliver_type = *op->entry[prev_ndx].deliver_type;
/* set copy in finished to null, thus preventing Delived
from being called twice */
*op->entry[prev_ndx].deliver_type =
GLOBUS_XIO_OPERATION_TYPE_FINISHED;
/* set the op ppinter to NULL for completeness */
op->entry[prev_ndx].deliver_type = NULL;
/* op ref count so that op stays around long enough to check
that it was restarted */
GlobusXIOOpInc(op);
}
}
globus_mutex_unlock(&context->mutex);
my_op->cb = (in_cb);
my_op->user_arg = (in_ua);
my_op->prev_ndx = prev_ndx;
if(deliver_type != GLOBUS_XIO_OPERATION_TYPE_FINISHED)
{
globus_i_xio_driver_deliver_op(op, prev_ndx, deliver_type);
}
/* op can be checked outside of lock */
if(pass)
{
res = globus_i_xio_driver_start_close(op, GLOBUS_TRUE);
}
}
if(res != GLOBUS_SUCCESS)
{
globus_mutex_lock(&context->mutex);
{
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_CLOSED);
context->ref--;
/* cant possibly be 0 if there is still an op */
globus_assert(context->ref > 0);
}
globus_mutex_unlock(&context->mutex);
}
GlobusXIODebugInternalExit();
return res;
}
void
globus_xio_driver_finished_close(
globus_xio_operation_t in_op,
globus_result_t in_res)
{
globus_i_xio_op_t * op;
globus_i_xio_context_entry_t * my_context;
globus_i_xio_context_t * context;
globus_i_xio_op_entry_t * my_op;
globus_result_t res;
globus_callback_space_t space =
GLOBUS_CALLBACK_GLOBAL_SPACE;
GlobusXIOName(globus_xio_driver_finished_close);
GlobusXIODebugInternalEnter();
res = (in_res);
op = (globus_i_xio_op_t *)(in_op);
globus_assert(op->ndx > 0);
op->progress = GLOBUS_TRUE;
op->block_timeout = GLOBUS_FALSE;
context = op->_op_context;
my_op = &op->entry[op->ndx - 1];
my_context = &context->entry[my_op->prev_ndx];
globus_mutex_lock(&context->mutex);
{
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_CLOSED);
context->ref--;
}
globus_mutex_unlock(&context->mutex);
globus_assert(op->ndx >= 0); /* otherwise we are not in bad memory */
op->cached_obj = GlobusXIOResultToObj(res);
if(my_op->prev_ndx == 0 && !op->blocking && op->_op_handle)
{
space = op->_op_handle->space;
}
if(my_op->in_register || space != GLOBUS_CALLBACK_GLOBAL_SPACE)
{
/* if this is a blocking op, we avoid the oneshot by delaying the
* finish until the stack unwinds
*/
if(op->blocking &&
GlobusXIOBlockedThreadMatchesCurrentThread(op->blocked_thread))
{
GlobusXIODebugDelayedFinish();
op->finished_delayed = GLOBUS_TRUE;
}
else
{
GlobusXIODebugInregisterOneShot();
globus_i_xio_register_oneshot(
op->_op_handle,
globus_l_xio_driver_op_close_kickout,
(void *)op,
space);
}
}
else
{
globus_l_xio_driver_op_close_kickout(op);
}
GlobusXIODebugInternalExit();
}
/************************************************************************
* write
* -----
***********************************************************************/
globus_result_t
globus_xio_driver_pass_write(
globus_xio_operation_t in_op,
globus_xio_iovec_t * in_iovec,
int in_iovec_count,
globus_size_t in_wait_for,
globus_xio_driver_data_callback_t in_cb,
void * in_user_arg)
{
globus_i_xio_op_t * op;
globus_i_xio_op_entry_t * my_op;
globus_i_xio_context_entry_t * my_context;
globus_i_xio_context_entry_t * next_context;
globus_i_xio_context_t * context;
globus_bool_t close = GLOBUS_FALSE;
int prev_ndx;
globus_result_t res = GLOBUS_SUCCESS;
globus_xio_driver_t driver;
globus_xio_operation_type_t deliver_type =
GLOBUS_XIO_OPERATION_TYPE_FINISHED;
globus_i_xio_handle_t * handle;
globus_bool_t destroy_handle = GLOBUS_FALSE;
GlobusXIOName(globus_xio_driver_pass_write);
GlobusXIODebugInternalEnter();
op = (in_op);
context = op->_op_context;
my_context = &context->entry[op->ndx];
op->progress = GLOBUS_TRUE;
op->block_timeout = GLOBUS_FALSE;
handle = op->_op_handle;
globus_assert(op->ndx < op->stack_size);
/* error checking */
globus_assert(my_context->state == GLOBUS_XIO_CONTEXT_STATE_OPEN ||
my_context->state == GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED ||
my_context->state == GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED);
if(op->canceled)
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] :Operation canceled\n"), _xio_name));
res = GlobusXIOErrorCanceled();
}
else
{
/* set up the entry */
prev_ndx = op->ndx;
do
{
next_context = &context->entry[op->ndx];
driver = next_context->driver;
op->ndx++;
}
while(driver->write_func == NULL);
op->entry[prev_ndx].next_ndx = op->ndx;
op->entry[prev_ndx].type = GLOBUS_XIO_OPERATION_TYPE_WRITE;
my_op = &op->entry[op->ndx - 1];
my_op->prev_ndx = prev_ndx;
my_op->_op_ent_data_cb = (in_cb);
my_op->user_arg = (in_user_arg);
my_op->_op_ent_iovec = (in_iovec);
my_op->_op_ent_iovec_count = (in_iovec_count);
my_op->_op_ent_nbytes = 0;
my_op->_op_ent_wait_for = (in_wait_for);
my_op->type = GLOBUS_XIO_OPERATION_TYPE_WRITE;
globus_mutex_lock(&context->mutex);
{
if(op->entry[prev_ndx].deliver_type != NULL)
{
/* make local copy */
deliver_type = *op->entry[prev_ndx].deliver_type;
/* set copy in finished to null, thus preventing Delived
from being called twice */
*op->entry[prev_ndx].deliver_type =
GLOBUS_XIO_OPERATION_TYPE_FINISHED;
/* set the op ppinter to NULL for completeness */
op->entry[prev_ndx].deliver_type = NULL;
/* op ref count so that op stays around long enough to check
that it was restarted */
GlobusXIOOpInc(op);
}
my_context->outstanding_operations++;
op->ref += 2; /* for pass and until finished */
}
globus_mutex_unlock(&context->mutex);
if(deliver_type != GLOBUS_XIO_OPERATION_TYPE_FINISHED)
{
globus_i_xio_driver_deliver_op(op, prev_ndx, deliver_type);
}
/* set the callstack flag */
my_op->in_register = GLOBUS_TRUE;
res = driver->write_func(
next_context->driver_handle,
my_op->_op_ent_iovec,
my_op->_op_ent_iovec_count,
op);
/* flip the callstack flag */
my_op->in_register = GLOBUS_FALSE;
if(res == GLOBUS_SUCCESS && prev_ndx == 0)
{
while(op->finished_delayed)
{
/* reuse this blocked thread to finish the operation */
op->finished_delayed = GLOBUS_FALSE;
globus_i_xio_driver_resume_op(op);
}
}
globus_mutex_lock(&context->mutex);
{
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
if(res != GLOBUS_SUCCESS)
{
globus_i_xio_pass_failed(op, my_context, &close,
&destroy_handle);
globus_assert(!destroy_handle);
}
}
globus_mutex_unlock(&context->mutex);
}
if(close)
{
globus_i_xio_driver_start_close(my_context->close_op,
GLOBUS_FALSE);
}
else if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
GlobusXIODebugInternalExit();
return res;
}
void
globus_xio_driver_finished_write(
globus_xio_operation_t in_op,
globus_result_t result,
globus_size_t nbytes)
{
globus_i_xio_op_t * op;
globus_i_xio_op_entry_t * my_op;
globus_result_t res;
globus_bool_t fire_cb = GLOBUS_TRUE;
globus_i_xio_context_entry_t * my_context;
globus_i_xio_context_t * context;
globus_callback_space_t space =
GLOBUS_CALLBACK_GLOBAL_SPACE;
GlobusXIOName(globus_xio_driver_finished_write);
GlobusXIODebugInternalEnter();
op = (globus_i_xio_op_t *)(in_op);
res = (result);
op->progress = GLOBUS_TRUE;
op->block_timeout = GLOBUS_FALSE;
context = op->_op_context;
my_op = &op->entry[op->ndx - 1];
my_context = &context->entry[my_op->prev_ndx];
op->cached_obj = GlobusXIOResultToObj(res);
globus_assert(my_context->state != GLOBUS_XIO_CONTEXT_STATE_OPENING &&
my_context->state != GLOBUS_XIO_CONTEXT_STATE_CLOSED);
my_op->_op_ent_nbytes += nbytes;
/* if not all bytes were written */
if(my_op->_op_ent_nbytes < my_op->_op_ent_wait_for &&
res == GLOBUS_SUCCESS)
{
/* if not enough bytes read set the fire_cb default to false */
fire_cb = GLOBUS_FALSE;
/* repass the operation down */
res = globus_i_xio_repass_write(op);
if(res != GLOBUS_SUCCESS)
{
fire_cb = GLOBUS_TRUE;
}
}
if(fire_cb)
{
if(my_op->_op_ent_fake_iovec != NULL)
{
globus_free(my_op->_op_ent_fake_iovec);
my_op->_op_ent_fake_iovec = NULL;
}
if(my_op->prev_ndx == 0 && !op->blocking && op->_op_handle)
{
space = op->_op_handle->space;
}
globus_assert(my_op->type == GLOBUS_XIO_OPERATION_TYPE_WRITE);
if(my_op->in_register || space != GLOBUS_CALLBACK_GLOBAL_SPACE)
{
/* if this is a blocking op, we avoid the oneshot by delaying the
* finish until the stack unwinds
*/
if(op->blocking &&
GlobusXIOBlockedThreadMatchesCurrentThread(op->blocked_thread))
{
GlobusXIODebugDelayedFinish();
op->finished_delayed = GLOBUS_TRUE;
}
else
{
GlobusXIODebugInregisterOneShot();
globus_i_xio_register_oneshot(
op->_op_handle,
globus_l_xio_driver_op_write_kickout,
(void *)op,
space);
}
}
else
{
globus_l_xio_driver_op_write_kickout(op);
}
}
GlobusXIODebugInternalExit();
}
void
globus_xio_driver_write_delivered(
globus_xio_operation_t in_op,
int in_ndx,
globus_xio_operation_type_t * deliver_type)
{
globus_i_xio_op_t * op;
globus_i_xio_op_t * close_op;
globus_i_xio_context_entry_t * my_context;
globus_i_xio_context_t * context;
globus_bool_t close = GLOBUS_FALSE;
globus_bool_t destroy_handle = GLOBUS_FALSE;
globus_i_xio_handle_t * handle;
GlobusXIOName(globus_xio_driver_write_delivered);
GlobusXIODebugInternalEnter();
op = (in_op);
context = op->_op_context;
my_context = &context->entry[in_ndx];
handle = op->_op_handle;
/* LOCK */
globus_mutex_lock(&context->mutex);
{
/* make sure it only gets delivered once */
if(deliver_type == NULL ||
*deliver_type == GLOBUS_XIO_OPERATION_TYPE_FINISHED)
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] : Already delivered\n"), _xio_name));
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
globus_mutex_unlock(&context->mutex);
goto exit;
}
op->entry[in_ndx].deliver_type = NULL;
*deliver_type = GLOBUS_XIO_OPERATION_TYPE_FINISHED;
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
globus_assert(my_context->outstanding_operations > 0);
my_context->outstanding_operations--;
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] : Context @ 0x%x State=%d Count=%d close_start=%d\n"),
_xio_name, my_context, my_context->state,
my_context->outstanding_operations,
my_context->close_started));
/* if we have a close delayed */
if((my_context->state == GLOBUS_XIO_CONTEXT_STATE_CLOSING ||
my_context->state ==
GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED_AND_CLOSING) &&
my_context->outstanding_operations == 0 &&
!my_context->close_started)
{
globus_assert(my_context->close_op != NULL);
close = GLOBUS_TRUE;
close_op = my_context->close_op;
my_context->close_started = GLOBUS_TRUE;
}
}
globus_mutex_unlock(&context->mutex);
if(close)
{
globus_i_xio_driver_start_close(close_op, GLOBUS_FALSE);
}
exit:
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
GlobusXIODebugInternalExit();
}
/************************************************************************
* read
* ----
***********************************************************************/
globus_result_t
globus_xio_driver_pass_read(
globus_xio_operation_t in_op,
globus_xio_iovec_t * in_iovec,
int in_iovec_count,
globus_size_t in_wait_for,
globus_xio_driver_data_callback_t in_cb,
void * in_user_arg)
{
globus_i_xio_op_t * op;
globus_i_xio_op_entry_t * my_op;
globus_i_xio_context_entry_t * next_context;
globus_i_xio_context_entry_t * my_context;
globus_i_xio_context_t * context;
int prev_ndx;
globus_result_t res = GLOBUS_SUCCESS;
globus_bool_t close = GLOBUS_FALSE;
globus_xio_driver_t driver;
globus_bool_t destroy_handle = GLOBUS_FALSE;
globus_bool_t pass = GLOBUS_TRUE;
globus_xio_operation_type_t deliver_type =
GLOBUS_XIO_OPERATION_TYPE_FINISHED;
GlobusXIOName(globus_xio_driver_pass_read);
GlobusXIODebugInternalEnter();
op = (in_op);
context = op->_op_context;
my_context = &context->entry[op->ndx];
op->progress = GLOBUS_TRUE;
op->block_timeout = GLOBUS_FALSE;
prev_ndx = op->ndx;
globus_assert(op->ndx < op->stack_size);
/* error checking */
globus_assert(my_context->state == GLOBUS_XIO_CONTEXT_STATE_OPEN ||
my_context->state == GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED ||
my_context->state == GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED);
if(op->canceled)
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] :Operation canceled\n"), _xio_name));
res = GlobusXIOErrorCanceled();
}
else
{
/* find next slot. start on next and find first interseted */
do
{
next_context = &context->entry[op->ndx];
driver = next_context->driver;
op->ndx++;
}
while(driver->read_func == NULL);
op->entry[prev_ndx].next_ndx = op->ndx;
op->entry[prev_ndx].type = GLOBUS_XIO_OPERATION_TYPE_READ;
my_op = &op->entry[op->ndx - 1];
my_op->prev_ndx = prev_ndx;
my_op->_op_ent_data_cb = (in_cb);
my_op->user_arg = (in_user_arg);
my_op->_op_ent_iovec = (in_iovec);
my_op->_op_ent_iovec_count = (in_iovec_count);
my_op->_op_ent_nbytes = 0;
my_op->_op_ent_wait_for = (in_wait_for);
my_op->type = GLOBUS_XIO_OPERATION_TYPE_READ;
globus_mutex_lock(&context->mutex);
{
if(op->entry[prev_ndx].deliver_type != NULL)
{
/* make local copy */
deliver_type = *op->entry[prev_ndx].deliver_type;
/* set copy in finished to null, thus preventing Delived
from being called twice */
*op->entry[prev_ndx].deliver_type =
GLOBUS_XIO_OPERATION_TYPE_FINISHED;
/* set the op ppinter to NULL for completeness */
op->entry[prev_ndx].deliver_type = NULL;
/* op ref count so that op stays around long enough to check
that it was restarted */
GlobusXIOOpInc(op);
}
if(my_context->state == GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED)
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("[%s]: Queuing read on eof list\n"), _xio_name));
op->cached_obj = GlobusXIOErrorObjEOF();
globus_list_insert(&my_context->eof_op_list, op);
op->ref++;
my_context->eof_operations++;
pass = GLOBUS_FALSE;
}
else if(
my_context->state == GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED ||
my_context->pending_reads > 0)
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("[%s]: Queuing read on pending queue\n"), _xio_name));
/* add this to the pending queue */
my_context->pending_reads++;
globus_fifo_enqueue(&my_context->pending_read_queue, op);
op->ref++;
pass = GLOBUS_FALSE;
}
else
{
my_context->read_operations++;
op->ref += 2; /* 1 for pass, 1 until finished */
}
my_context->outstanding_operations++;
}
globus_mutex_unlock(&context->mutex);
if(deliver_type != GLOBUS_XIO_OPERATION_TYPE_FINISHED)
{
globus_i_xio_driver_deliver_op(op, prev_ndx, deliver_type);
}
if(pass)
{
/* set the callstack flag */
my_op->in_register = GLOBUS_TRUE;
res = driver->read_func(
next_context->driver_handle,
my_op->_op_ent_iovec,
my_op->_op_ent_iovec_count,
op);
/* flip the callstack flag */
my_op->in_register = GLOBUS_FALSE;
if(res == GLOBUS_SUCCESS && prev_ndx == 0)
{
while(op->finished_delayed)
{
/* reuse this blocked thread to finish the operation */
op->finished_delayed = GLOBUS_FALSE;
globus_i_xio_driver_resume_op(op);
}
}
globus_mutex_lock(&context->mutex);
{
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
globus_assert(!destroy_handle);
}
if(res != GLOBUS_SUCCESS)
{
globus_i_xio_pass_failed(op, my_context, &close,
&destroy_handle);
globus_assert(!destroy_handle);
my_context->read_operations--;
if(my_context->read_operations == 0 &&
(my_context->state ==
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED ||
my_context->state ==
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED_AND_CLOSING))
{
globus_l_xio_driver_purge_read_eof(my_context);
}
}
}
globus_mutex_unlock(&context->mutex);
}
}
if(close)
{
globus_i_xio_driver_start_close(my_context->close_op,
GLOBUS_FALSE);
}
GlobusXIODebugInternalExit();
return res;
}
void
globus_xio_driver_finished_read(
globus_xio_operation_t in_op,
globus_result_t result,
globus_size_t nbytes)
{
globus_i_xio_op_t * op;
globus_i_xio_op_entry_t * my_op;
globus_result_t res;
globus_bool_t fire_cb = GLOBUS_TRUE;
globus_i_xio_context_entry_t * my_context;
globus_i_xio_context_t * context;
globus_callback_space_t space =
GLOBUS_CALLBACK_GLOBAL_SPACE;
GlobusXIOName(globus_xio_driver_finished_read);
GlobusXIODebugInternalEnter();
op = (globus_i_xio_op_t *)(in_op);
res = (result);
op->progress = GLOBUS_TRUE;
op->block_timeout = GLOBUS_FALSE;
context = op->_op_context;
my_op = &op->entry[op->ndx - 1];
my_context = &context->entry[my_op->prev_ndx];
globus_assert(op->ndx > 0);
globus_assert(my_context->state != GLOBUS_XIO_CONTEXT_STATE_OPENING &&
my_context->state != GLOBUS_XIO_CONTEXT_STATE_CLOSED);
my_op->_op_ent_nbytes += nbytes;
if(res != GLOBUS_SUCCESS && globus_xio_error_is_eof(res))
{
globus_mutex_lock(&context->mutex);
{
switch(my_context->state)
{
case GLOBUS_XIO_CONTEXT_STATE_OPEN:
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED);
break;
case GLOBUS_XIO_CONTEXT_STATE_CLOSING:
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED_AND_CLOSING);
break;
case GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED_AND_CLOSING:
case GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED:
break;
default:
globus_assert(0);
break;
}
my_context->read_operations--;
my_context->eof_operations++;
if(my_context->read_operations > 0)
{
op->cached_obj = GlobusXIOResultToObj(res);
globus_list_insert(&my_context->eof_op_list, op);
fire_cb = GLOBUS_FALSE;
}
}
globus_mutex_unlock(&context->mutex);
}
/* if not all bytes were read */
else if(my_op->_op_ent_nbytes < my_op->_op_ent_wait_for &&
res == GLOBUS_SUCCESS)
{
/* if not enough bytes read set the fire_cb deafult to false */
fire_cb = GLOBUS_FALSE;
res = globus_i_xio_repass_read(op);
if(res != GLOBUS_SUCCESS)
{
fire_cb = GLOBUS_TRUE;
}
}
if(fire_cb)
{
/* if a temp iovec struct was used for fullfulling waitfor,
we can free it now */
if(my_op->_op_ent_fake_iovec != NULL)
{
globus_free(my_op->_op_ent_fake_iovec);
my_op->_op_ent_fake_iovec = NULL;
}
if(my_op->prev_ndx == 0 && !op->blocking && op->_op_handle)
{
space = op->_op_handle->space;
}
op->cached_obj = GlobusXIOResultToObj(res);
globus_assert(my_op->type == GLOBUS_XIO_OPERATION_TYPE_READ);
if(my_op->in_register || space != GLOBUS_CALLBACK_GLOBAL_SPACE)
{
/* if this is a blocking op, we avoid the oneshot by delaying the
* finish until the stack unwinds
*/
if(op->blocking &&
GlobusXIOBlockedThreadMatchesCurrentThread(op->blocked_thread))
{
GlobusXIODebugDelayedFinish();
op->finished_delayed = GLOBUS_TRUE;
}
else
{
GlobusXIODebugInregisterOneShot();
globus_i_xio_register_oneshot(
op->_op_handle,
globus_l_xio_driver_op_read_kickout,
(void *)op,
space);
}
}
else
{
globus_l_xio_driver_op_read_kickout(op);
}
}
GlobusXIODebugInternalExit();
}
static
void
globus_l_xio_pass_pending_reads(
globus_i_xio_context_entry_t * my_context)
{
globus_i_xio_context_t * context;
globus_bool_t destroy_context;
globus_i_xio_op_t * op;
GlobusXIOName(globus_l_xio_pass_pending_reads);
GlobusXIODebugInternalEnter();
context = my_context->whos_my_daddy;
destroy_context = GLOBUS_FALSE;
globus_mutex_lock(&context->mutex);
/* this holds a reference on read operations to prevent any eofs from
* being delivered before I can dump this pending queue into the eof
* queue
*/
my_context->read_operations++;
context->ref++;
while(my_context->pending_reads > 0)
{
/* I hold an outstanding read operation so it shouldn't be possible
* to enter EOF_DELIVERED here
*/
globus_assert(my_context->state !=
GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED);
if(my_context->state == GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED ||
my_context->state ==
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED_AND_CLOSING)
{
/* one of the reads we just dispatched caused an eof, dump
* the remaining in the eof queue
*/
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("[%s]: Dumping pending queue into eof list\n"), _xio_name));
do
{
my_context->pending_reads--;
op = (globus_i_xio_op_t *)
globus_fifo_dequeue(&my_context->pending_read_queue);
op->cached_obj = GlobusXIOErrorObjEOF();
globus_list_insert(&my_context->eof_op_list, op);
my_context->eof_operations++;
} while(my_context->pending_reads > 0);
op = NULL;
}
else
{
my_context->pending_reads--;
op = (globus_i_xio_op_t *)
globus_fifo_dequeue(&my_context->pending_read_queue);
my_context->read_operations++;
op->ref++; /* for the pass */
}
if(op)
{
globus_i_xio_op_entry_t * my_op;
globus_i_xio_context_entry_t * next_context;
globus_result_t res;
globus_bool_t destroy_handle;
globus_mutex_unlock(&context->mutex);
my_op = &op->entry[op->ndx - 1];
next_context = &context->entry[op->ndx - 1];
my_op->in_register = GLOBUS_TRUE;
if(op->canceled)
{
res = GlobusXIOErrorCanceled();
}
else
{
res = next_context->driver->read_func(
next_context->driver_handle,
my_op->_op_ent_iovec,
my_op->_op_ent_iovec_count,
op);
}
if(res != GLOBUS_SUCCESS)
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("[%s]: Pending read failed, finishing now\n"), _xio_name));
globus_xio_driver_finished_read(op, res, 0);
}
my_op->in_register = GLOBUS_FALSE;
globus_mutex_lock(&context->mutex);
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
globus_assert(!destroy_handle);
}
}
}
/* remove read operation reference and purge eofs if there are no
* outstanding reads
*/
my_context->read_operations--;
if(my_context->read_operations == 0 &&
(my_context->state == GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED ||
my_context->state ==
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED_AND_CLOSING))
{
globus_l_xio_driver_purge_read_eof(my_context);
}
context->ref--;
if(context->ref == 0)
{
destroy_context = GLOBUS_TRUE;
}
globus_mutex_unlock(&context->mutex);
if(destroy_context)
{
globus_i_xio_context_destroy(context);
}
GlobusXIODebugInternalExit();
}
void
globus_xio_driver_read_delivered(
globus_xio_operation_t op,
int in_ndx,
globus_xio_operation_type_t * deliver_type)
{
globus_i_xio_context_entry_t * my_context;
globus_bool_t purge_eof;
globus_bool_t dispatch_pending = GLOBUS_FALSE;
globus_bool_t close = GLOBUS_FALSE;
globus_i_xio_context_t * context;
globus_bool_t destroy_handle = GLOBUS_FALSE;
globus_i_xio_handle_t * handle;
GlobusXIOName(globus_xio_driver_read_delivered);
GlobusXIODebugInternalEnter();
context = op->_op_context;
my_context = &context->entry[in_ndx];
handle = op->_op_handle;
globus_mutex_lock(&context->mutex);
{
/* make sure it only gets delivered once */
if(deliver_type == NULL ||
*deliver_type == GLOBUS_XIO_OPERATION_TYPE_FINISHED)
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] : Already delivered\n"), _xio_name));
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
globus_mutex_unlock(&context->mutex);
goto exit;
}
*deliver_type = GLOBUS_XIO_OPERATION_TYPE_FINISHED;
op->entry[in_ndx].deliver_type = NULL;
GlobusXIOOpDec(op);
if(op->ref == 0)
{
globus_i_xio_op_destroy(op, &destroy_handle);
}
purge_eof = GLOBUS_FALSE;
if(my_context->read_operations == 0)
{
/* just delivered an eof op */
switch(my_context->state)
{
case GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED:
purge_eof = GLOBUS_TRUE;
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED);
break;
case GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED_AND_CLOSING:
purge_eof = GLOBUS_TRUE;
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED_AND_CLOSING);
break;
case GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED_AND_CLOSING:
case GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED:
break;
default:
globus_assert(0);
}
my_context->eof_operations--;
if(my_context->eof_operations == 0)
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO,
(_XIOSL("[%s]: All eof ops delivered\n"), _xio_name));
if(my_context->state == GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED)
{
GlobusXIOContextStateChange(my_context,
GLOBUS_XIO_CONTEXT_STATE_OPEN);
}
if(my_context->pending_reads > 0)
{
dispatch_pending = GLOBUS_TRUE;
}
}
}
else
{
my_context->read_operations--;
/* if no more read operations are outstanding and we are waiting
* on EOF, purge eof list */
if(my_context->read_operations == 0 &&
(my_context->state ==
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED ||
my_context->state ==
GLOBUS_XIO_CONTEXT_STATE_EOF_RECEIVED_AND_CLOSING))
{
purge_eof = GLOBUS_TRUE;
}
}
my_context->outstanding_operations--;
if(purge_eof)
{
globus_l_xio_driver_purge_read_eof(my_context);
}
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] : Context @ 0x%x State=%d Count=%d close_start=%d\n"),
_xio_name, my_context, my_context->state,
my_context->outstanding_operations,
my_context->close_started));
globus_assert(my_context->outstanding_operations >= 0);
if((my_context->state == GLOBUS_XIO_CONTEXT_STATE_CLOSING ||
my_context->state ==
GLOBUS_XIO_CONTEXT_STATE_EOF_DELIVERED_AND_CLOSING) &&
my_context->outstanding_operations == 0 &&
!my_context->close_started)
{
close = GLOBUS_TRUE;
my_context->close_started = GLOBUS_TRUE;
}
}
globus_mutex_unlock(&context->mutex);
if(dispatch_pending)
{
globus_l_xio_pass_pending_reads(my_context);
}
if(close)
{
globus_i_xio_driver_start_close(my_context->close_op, GLOBUS_FALSE);
}
exit:
if(destroy_handle)
{
globus_i_xio_handle_destroy(handle);
}
GlobusXIODebugInternalExit();
}
/************************************************************************
* accept
* ------
***********************************************************************/
globus_result_t
globus_xio_driver_pass_accept(
globus_xio_operation_t in_op,
globus_xio_driver_callback_t in_cb,
void * in_user_arg)
{
globus_i_xio_op_t * op;
globus_i_xio_server_t * server;
globus_i_xio_server_entry_t * my_server;
globus_i_xio_op_entry_t * my_op;
int prev_ndx;
globus_result_t res;
globus_xio_driver_t driver;
GlobusXIOName(globus_xio_driver_pass_accept);
GlobusXIODebugInternalEnter();
op = (globus_i_xio_op_t *)(in_op);
globus_assert(op->ndx < op->stack_size);
server = op->_op_server;
op->progress = GLOBUS_TRUE;
op->block_timeout = GLOBUS_FALSE;
if(op->canceled)
{
GlobusXIODebugPrintf(GLOBUS_XIO_DEBUG_INFO_VERBOSE,
(_XIOSL("[%s] :Operation canceled\n"), _xio_name));
res = GlobusXIOErrorCanceled();
}
else
{
prev_ndx = op->ndx;
do
{
my_op = &op->entry[op->ndx];
my_server = &server->entry[op->ndx];
driver = my_server->driver;
op->ndx++;
}
while(driver->server_accept_func == NULL);
my_op->type = GLOBUS_XIO_OPERATION_TYPE_ACCEPT;
my_op->cb = (in_cb);
my_op->user_arg = (in_user_arg);
my_op->prev_ndx = (prev_ndx);
my_op->in_register = GLOBUS_TRUE;
res = driver->server_accept_func(
my_server->server_handle,
op);
my_op->in_register = GLOBUS_FALSE;
if(res == GLOBUS_SUCCESS && prev_ndx == 0)
{
while(op->finished_delayed)
{
/* reuse this blocked thread to finish the operation */
op->finished_delayed = GLOBUS_FALSE;
globus_l_xio_driver_op_accept_kickout(op);
}
}
}
GlobusXIODebugInternalExit();
return res;
}
void
globus_xio_driver_finished_accept(
globus_xio_operation_t in_op,
void * in_link,
globus_result_t in_res)
{
globus_i_xio_op_t * op;
globus_i_xio_op_entry_t * my_op;
globus_callback_space_t space =
GLOBUS_CALLBACK_GLOBAL_SPACE;
GlobusXIOName(globus_xio_driver_finished_accept);
GlobusXIODebugInternalEnter();
op = (globus_i_xio_op_t *)(in_op);
globus_assert(op->ndx > 0);
op->progress = GLOBUS_TRUE;
op->block_timeout = GLOBUS_FALSE;
my_op = &op->entry[op->ndx - 1];
op->cached_obj = GlobusXIOResultToObj((in_res));
my_op->link = (in_link);
if(my_op->prev_ndx == 0 && !op->blocking)
{
space = op->_op_server->space;
}
if(my_op->in_register || space != GLOBUS_CALLBACK_GLOBAL_SPACE)
{
/* if this is a blocking op, we avoid the oneshot by delaying the
* finish until the stack unwinds
*/
if(op->blocking &&
GlobusXIOBlockedThreadMatchesCurrentThread(op->blocked_thread))
{
GlobusXIODebugDelayedFinish();
op->finished_delayed = GLOBUS_TRUE;
}
else
{
GlobusXIODebugInregisterOneShot();
globus_i_xio_register_oneshot(
NULL,
globus_l_xio_driver_op_accept_kickout,
(void *)op,
space);
}
}
else
{
globus_l_xio_driver_op_accept_kickout(op);
}
GlobusXIODebugInternalExit();
}
globus_result_t
globus_xio_driver_pass_server_init(
globus_xio_operation_t op,
const globus_xio_contact_t * contact_info,
void * driver_server)
{
globus_i_xio_server_t * server;
globus_result_t res;
GlobusXIOName(globus_xio_driver_pass_server_init);
GlobusXIODebugInternalEnter();
server = op->_op_server;
op->progress = GLOBUS_TRUE;
op->block_timeout = GLOBUS_FALSE;
if(op->ndx < op->stack_size)
{
server->entry[op->ndx].server_handle = driver_server;
}
while(--op->ndx >= 0 &&
server->entry[op->ndx].driver->server_init_func == NULL)
{ }
if(op->ndx >= 0)
{
res = server->entry[op->ndx].driver->server_init_func(
op->entry[op->ndx].open_attr,
contact_info,
op);
}
else
{
res = globus_xio_contact_info_to_string(
contact_info, &server->contact_string);
}
GlobusXIODebugInternalExit();
return res;
}
globus_xio-6.6/PaxHeaders.22691/globus_xio_util.c 0000644 0000000 0000000 00000000132 14243161125 020111 x ustar 00 0000000 0000000 30 mtime=1653400149.725966402
30 atime=1653401489.192566055
30 ctime=1653403998.755961465
globus_xio-6.6/globus_xio_util.c 0000664 0001750 0001750 00000005534 14243161125 020260 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "globus_xio_util.h"
#include "globus_xio_types.h"
#include "globus_common.h"
globus_bool_t
globus_xio_get_env_pair(
const char * env_name,
int * min,
int * max)
{
char * min_max;
GlobusXIOName(globus_xio_get_env_pair);
min_max = globus_module_getenv(env_name);
if(min_max && sscanf(min_max, " %d , %d", min, max) == 2)
{
return GLOBUS_TRUE;
}
return GLOBUS_FALSE;
}
globus_bool_t
globus_xio_error_is_eof(
globus_result_t res)
{
return globus_error_match(
globus_error_peek(res), GLOBUS_XIO_MODULE, GLOBUS_XIO_ERROR_EOF);
}
globus_bool_t
globus_xio_error_is_canceled(
globus_result_t res)
{
return globus_error_match(
globus_error_peek(res), GLOBUS_XIO_MODULE, GLOBUS_XIO_ERROR_CANCELED);
}
globus_bool_t
globus_xio_error_match(
globus_result_t result,
int type)
{
return globus_error_match(
globus_error_peek(result), GLOBUS_XIO_MODULE, type);
}
globus_result_t
globus_xio_contact_copy(
globus_xio_contact_t * dst,
const globus_xio_contact_t * src)
{
globus_result_t result;
GlobusXIOName(globus_xio_contact_copy);
if(dst == NULL)
{
result = GlobusXIOErrorParameter("dst");
goto error;
}
if(src == NULL)
{
result = GlobusXIOErrorParameter("src");
goto error;
}
memset(dst, '\0', sizeof(globus_xio_contact_t));
if(src->unparsed)
{
dst->unparsed = strdup(src->unparsed);
}
if(src->resource)
{
dst->resource = strdup(src->resource);
}
if(src->host)
{
dst->host = strdup(src->host);
}
if(src->port)
{
dst->port = strdup(src->port);
}
if(src->scheme)
{
dst->scheme = strdup(src->scheme);
}
if(src->user)
{
dst->user = strdup(src->user);
}
if(src->pass)
{
dst->pass = strdup(src->pass);
}
if(src->subject)
{
dst->subject = strdup(src->subject);
}
return GLOBUS_SUCCESS;
error:
return result;
}
globus_xio-6.6/PaxHeaders.22691/globus_xio_wrapblock.c 0000644 0000000 0000000 00000000132 14243161125 021120 x ustar 00 0000000 0000000 30 mtime=1653400149.726966392
30 atime=1653401489.597562048
30 ctime=1653403998.757961446
globus_xio-6.6/globus_xio_wrapblock.c 0000664 0001750 0001750 00000033200 14243161125 021256 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2014 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "globus_i_xio.h"
#include "globus_xio_driver.h"
#include "globus_xio.h"
#include "globus_xio_load.h"
#include "globus_common.h"
#include "globus_xio_wrapblock.h"
typedef struct xio_l_wrapblock_handle_s
{
void * driver_handle;
struct xio_l_wrapblock_driver_s * wrapblock_driver;
} xio_l_wrapblock_handle_t;
typedef struct xio_l_wrapblock_wrapper_s
{
globus_xio_contact_t ci;
globus_i_xio_driver_t * driver;
struct xio_l_wrapblock_driver_s * wrapblock_driver;
xio_l_wrapblock_handle_t * wrapblock_handle;
void * attr;
void * link;
globus_xio_iovec_t * iovec;
int iovec_count;
globus_xio_operation_t op;
} xio_l_wrapblock_wrapper_t;
typedef struct xio_l_wrapblock_driver_s
{
globus_xio_wrapblock_open_func_t open_func;
globus_xio_wrapblock_close_func_t close_func;
globus_xio_wrapblock_read_func_t read_func;
globus_xio_wrapblock_write_func_t write_func;
globus_xio_wrapblock_accept_func_t accept_func;
} xio_l_wrapblock_driver_t;
static
void
xio_l_wrapblock_wrapper_destroy(
xio_l_wrapblock_wrapper_t * wrapper)
{
globus_xio_contact_destroy(&wrapper->ci);
if(wrapper->iovec != NULL)
{
globus_free(wrapper->iovec);
}
if(wrapper->attr && wrapper->driver && wrapper->driver->attr_destroy_func)
{
wrapper->driver->attr_destroy_func(wrapper->attr);
}
globus_free(wrapper);
}
/************************************************************************
* iface functions
* ---------------
*
***********************************************************************/
static
void
globus_l_xio_wrapblock_accept_kickout(
void * user_arg)
{
void * link;
globus_result_t res;
xio_l_wrapblock_wrapper_t * wrapper;
globus_thread_blocking_will_block();
wrapper = (xio_l_wrapblock_wrapper_t *) user_arg;
res = wrapper->wrapblock_driver->accept_func(
wrapper->attr,
&link);
globus_xio_driver_finished_accept(
wrapper->op, link, res);
xio_l_wrapblock_wrapper_destroy(wrapper);
}
static
globus_result_t
globus_l_xio_wrapblock_server_accept(
void * driver_server,
globus_xio_operation_t op)
{
xio_l_wrapblock_wrapper_t * wrapper;
globus_xio_driver_t driver;
globus_i_xio_op_t * xio_op;
xio_op = (globus_i_xio_op_t *) op;
driver = xio_op->_op_server->entry[op->ndx - 1].driver;
wrapper = (xio_l_wrapblock_wrapper_t *)
globus_calloc(1, sizeof(xio_l_wrapblock_wrapper_t));
wrapper->wrapblock_driver = driver->wrap_data;
wrapper->attr = driver_server;
wrapper->op = op;
globus_callback_register_oneshot(
NULL,
NULL,
globus_l_xio_wrapblock_accept_kickout,
wrapper);
return GLOBUS_SUCCESS;
}
static
void
globus_l_xio_wrapblock_open_kickout(
void * user_arg)
{
globus_result_t res;
xio_l_wrapblock_wrapper_t * wrapper;
globus_thread_blocking_will_block();
wrapper = (xio_l_wrapblock_wrapper_t *) user_arg;
res = wrapper->wrapblock_handle->wrapblock_driver->open_func(
&wrapper->ci,
wrapper->link,
wrapper->attr,
&wrapper->wrapblock_handle->driver_handle);
globus_xio_driver_finished_open(
wrapper->wrapblock_handle, wrapper->op, res);
xio_l_wrapblock_wrapper_destroy(wrapper);
}
static
globus_result_t
globus_l_xio_wrapblock_open(
const globus_xio_contact_t * contact_info,
void * driver_link,
void * driver_attr,
globus_xio_operation_t op)
{
globus_result_t result;
xio_l_wrapblock_wrapper_t * wrapper;
xio_l_wrapblock_handle_t * wrapblock_handle;
globus_xio_driver_t driver;
globus_i_xio_op_t * xio_op;
xio_op = (globus_i_xio_op_t *) op;
driver = xio_op->_op_context->entry[op->ndx - 1].driver;
wrapblock_handle = globus_calloc(1, sizeof(xio_l_wrapblock_handle_t));
wrapblock_handle->wrapblock_driver = driver->wrap_data;
if(globus_xio_driver_operation_is_blocking(op))
{
result = wrapblock_handle->wrapblock_driver->open_func(
contact_info,
driver_link,
driver_attr,
&wrapblock_handle->driver_handle);
globus_xio_driver_finished_open(wrapblock_handle, op, result);
}
else
{
wrapper = (xio_l_wrapblock_wrapper_t *)
globus_calloc(1, sizeof(xio_l_wrapblock_wrapper_t));
wrapper->wrapblock_handle = wrapblock_handle;
wrapper->link = driver_link;
wrapper->op = op;
wrapper->driver = driver;
if(driver_attr != NULL && driver->attr_copy_func != NULL)
{
driver->attr_copy_func(&wrapper->attr, driver_attr);
}
/* gotta copy contact info the hard way */
globus_xio_contact_copy(&wrapper->ci, contact_info);
globus_callback_register_oneshot(
NULL,
NULL,
globus_l_xio_wrapblock_open_kickout,
wrapper);
}
return GLOBUS_SUCCESS;
}
static
void
globus_l_xio_wrapblock_write_kickout(
void * user_arg)
{
globus_size_t nbytes;
globus_result_t result;
xio_l_wrapblock_wrapper_t * wrapper;
globus_thread_blocking_will_block();
wrapper = (xio_l_wrapblock_wrapper_t *) user_arg;
result = wrapper->wrapblock_handle->wrapblock_driver->write_func(
wrapper->wrapblock_handle->driver_handle,
wrapper->iovec,
wrapper->iovec_count,
&nbytes);
globus_xio_driver_finished_write(wrapper->op, result, nbytes);
xio_l_wrapblock_wrapper_destroy(wrapper);
}
static
globus_result_t
globus_l_xio_wrapblock_write(
void * driver_specific_handle,
const globus_xio_iovec_t * iovec,
int iovec_count,
globus_xio_operation_t op)
{
globus_size_t nbytes;
globus_result_t result;
int i;
xio_l_wrapblock_wrapper_t * wrapper;
xio_l_wrapblock_handle_t * wrapblock_handle;
wrapblock_handle = (xio_l_wrapblock_handle_t *) driver_specific_handle;
if(globus_xio_driver_operation_is_blocking(op))
{
result = wrapblock_handle->wrapblock_driver->write_func(
wrapblock_handle->driver_handle,
iovec,
iovec_count,
&nbytes);
globus_xio_driver_finished_write(op, result, nbytes);
}
else
{
wrapper = (xio_l_wrapblock_wrapper_t *)
globus_calloc(1, sizeof(xio_l_wrapblock_wrapper_t));
wrapper->iovec = (globus_xio_iovec_t *)
globus_calloc(iovec_count, sizeof(globus_xio_iovec_t));
wrapper->iovec_count = iovec_count;
wrapper->op = op;
wrapper->wrapblock_handle = driver_specific_handle;
for(i = 0; i < iovec_count; i++)
{
wrapper->iovec[i].iov_base = iovec[i].iov_base;
wrapper->iovec[i].iov_len = iovec[i].iov_len;
}
globus_callback_register_oneshot(
NULL,
NULL,
globus_l_xio_wrapblock_write_kickout,
wrapper);
}
return GLOBUS_SUCCESS;
}
static
void
globus_l_xio_wrapblock_read_kickout(
void * user_arg)
{
globus_size_t nbytes;
globus_result_t result;
xio_l_wrapblock_wrapper_t * wrapper;
globus_thread_blocking_will_block();
wrapper = (xio_l_wrapblock_wrapper_t *) user_arg;
result = wrapper->wrapblock_handle->wrapblock_driver->read_func(
wrapper->wrapblock_handle->driver_handle,
wrapper->iovec,
wrapper->iovec_count,
&nbytes);
globus_xio_driver_finished_read(wrapper->op, result, nbytes);
xio_l_wrapblock_wrapper_destroy(wrapper);
}
static
globus_result_t
globus_l_xio_wrapblock_read(
void * driver_specific_handle,
const globus_xio_iovec_t * iovec,
int iovec_count,
globus_xio_operation_t op)
{
globus_size_t nbytes;
globus_result_t result;
int i;
xio_l_wrapblock_wrapper_t * wrapper;
xio_l_wrapblock_handle_t * wrapblock_handle;
wrapblock_handle = (xio_l_wrapblock_handle_t *) driver_specific_handle;
if(globus_xio_driver_operation_is_blocking(op))
{
result = wrapblock_handle->wrapblock_driver->read_func(
wrapblock_handle->driver_handle,
iovec,
iovec_count,
&nbytes);
globus_xio_driver_finished_read(op, result, nbytes);
}
else
{
wrapper = (xio_l_wrapblock_wrapper_t *)
globus_calloc(1, sizeof(xio_l_wrapblock_wrapper_t));
wrapper->iovec = (globus_xio_iovec_t *)
globus_calloc(iovec_count, sizeof(globus_xio_iovec_t));
wrapper->iovec_count = iovec_count;
wrapper->op = op;
wrapper->wrapblock_handle = driver_specific_handle;
for(i = 0; i < iovec_count; i++)
{
wrapper->iovec[i].iov_base = iovec[i].iov_base;
wrapper->iovec[i].iov_len = iovec[i].iov_len;
}
globus_callback_register_oneshot(
NULL,
NULL,
globus_l_xio_wrapblock_read_kickout,
wrapper);
}
return GLOBUS_SUCCESS;
}
static
void
globus_l_xio_wrapblock_close_kickout(
void * user_arg)
{
xio_l_wrapblock_handle_t * wrapblock_handle;
globus_result_t result;
xio_l_wrapblock_wrapper_t * wrapper;
globus_thread_blocking_will_block();
wrapper = (xio_l_wrapblock_wrapper_t *) user_arg;
wrapblock_handle = wrapper->wrapblock_handle;
result = wrapper->wrapblock_handle->wrapblock_driver->close_func(
wrapblock_handle->driver_handle,
wrapper->attr);
globus_xio_driver_finished_close(wrapper->op, result);
xio_l_wrapblock_wrapper_destroy(wrapper);
globus_free(wrapblock_handle);
}
static
globus_result_t
globus_l_xio_wrapblock_close(
void * driver_specific_handle,
void * attr,
globus_xio_operation_t op)
{
globus_result_t result;
xio_l_wrapblock_wrapper_t * wrapper;
xio_l_wrapblock_handle_t * wrapblock_handle;
wrapblock_handle = (xio_l_wrapblock_handle_t *) driver_specific_handle;
if(globus_xio_driver_operation_is_blocking(op))
{
result = wrapblock_handle->wrapblock_driver->close_func(
wrapblock_handle->driver_handle,
attr);
globus_xio_driver_finished_close(op, result);
globus_free(wrapblock_handle);
}
else
{
wrapper = (xio_l_wrapblock_wrapper_t *)
globus_calloc(1, sizeof(xio_l_wrapblock_wrapper_t));
wrapper->attr = attr;
wrapper->op = op;
wrapper->wrapblock_handle = driver_specific_handle;
globus_callback_register_oneshot(
NULL,
NULL,
globus_l_xio_wrapblock_close_kickout,
wrapper);
}
return GLOBUS_SUCCESS;
}
globus_result_t
globus_xio_wrapblock_init(
globus_xio_driver_t driver,
globus_xio_wrapblock_open_func_t open_func,
globus_xio_wrapblock_close_func_t close_func,
globus_xio_wrapblock_read_func_t read_func,
globus_xio_wrapblock_write_func_t write_func,
globus_xio_wrapblock_accept_func_t accept_func)
{
xio_l_wrapblock_driver_t * wrapblock_driver;
if(open_func != NULL)
{
driver->transport_open_func = globus_l_xio_wrapblock_open;
}
if(close_func != NULL)
{
driver->close_func = globus_l_xio_wrapblock_close;
}
if(read_func != NULL)
{
driver->read_func = globus_l_xio_wrapblock_read;
}
if(write_func != NULL)
{
driver->write_func = globus_l_xio_wrapblock_write;
}
if(accept_func != NULL)
{
driver->server_accept_func = globus_l_xio_wrapblock_server_accept;
}
wrapblock_driver = (xio_l_wrapblock_driver_t *)
globus_calloc(1, sizeof(xio_l_wrapblock_driver_t));
wrapblock_driver->open_func = open_func;
wrapblock_driver->close_func = close_func;
wrapblock_driver->read_func = read_func;
wrapblock_driver->write_func = write_func;
wrapblock_driver->accept_func = accept_func;
driver->wrap_data = wrapblock_driver;
return GLOBUS_SUCCESS;
}
globus_xio-6.6/PaxHeaders.22691/globus_xio_system_select.c 0000644 0000000 0000000 00000000132 14243161125 022017 x ustar 00 0000000 0000000 30 mtime=1653400149.725966402
30 atime=1653401489.961558446
30 ctime=1653403998.759961427
globus_xio-6.6/globus_xio_system_select.c 0000664 0001750 0001750 00000222115 14243161125 022162 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "globus_i_xio_config.h"
#include "globus_common.h"
#ifndef TARGET_ARCH_WIN32
#include "globus_xio_system.h"
#include "globus_i_xio_system_common.h"
#include "globus_xio_driver.h"
#include
#include
#ifdef HAVE_SYSCONF
#define GLOBUS_L_OPEN_MAX sysconf(_SC_OPEN_MAX)
#else
#define GLOBUS_L_OPEN_MAX 256
#endif
typedef struct globus_l_xio_system_s
{
globus_xio_system_type_t type;
int fd;
globus_mutex_t lock; /* only used to protect below */
globus_off_t file_position;
} globus_l_xio_system_t;
static
int
globus_l_xio_system_activate(void);
static
int
globus_l_xio_system_deactivate(void);
#include "version.h"
globus_module_descriptor_t globus_i_xio_system_module =
{
"globus_xio_system_select",
globus_l_xio_system_activate,
globus_l_xio_system_deactivate,
GLOBUS_NULL,
GLOBUS_NULL,
&local_version
};
static globus_cond_t globus_l_xio_system_cond;
static globus_mutex_t globus_l_xio_system_fdset_mutex;
static globus_mutex_t globus_l_xio_system_cancel_mutex;
static globus_bool_t globus_l_xio_system_select_active;
static globus_bool_t globus_l_xio_system_wakeup_pending;
static globus_bool_t globus_l_xio_system_shutdown_called;
static int globus_l_xio_system_highest_fd;
static int globus_l_xio_system_max_fds;
static int globus_l_xio_system_fd_allocsize;
static fd_set * globus_l_xio_system_read_fds;
static fd_set * globus_l_xio_system_write_fds;
static fd_set * globus_l_xio_system_ready_reads;
static fd_set * globus_l_xio_system_ready_writes;
static globus_list_t * globus_l_xio_system_canceled_reads;
static globus_list_t * globus_l_xio_system_canceled_writes;
static globus_i_xio_system_op_info_t ** globus_l_xio_system_read_operations;
static globus_i_xio_system_op_info_t ** globus_l_xio_system_write_operations;
static int globus_l_xio_system_wakeup_pipe[2];
static globus_callback_handle_t globus_l_xio_system_poll_handle;
/* In the pre-activation of the thread module, we
* are setting up some code to block the SIGPIPE
* signal. This is necessary because some of
* the TCP protocols we are using do not have
* a mode in which we can safely detect a remotely-
* closing socket.
*/
static
void
globus_l_xio_system_poll(
void * user_args);
static
void
globus_l_xio_system_kickout(
void * user_arg);
static
void
globus_l_xio_system_select_wakeup(void);
static
void
globus_l_xio_system_unregister_read(
int fd);
static
void
globus_l_xio_system_unregister_write(
int fd);
static
int
globus_l_xio_system_add_nonblocking(
globus_l_xio_system_t * handle);
static
int
globus_l_xio_system_remove_nonblocking(
globus_l_xio_system_t * handle);
static
globus_result_t
globus_l_xio_system_try_read(
globus_l_xio_system_t * handle,
globus_off_t offset,
const globus_xio_iovec_t * iov,
int iovc,
int flags,
globus_sockaddr_t * from,
globus_size_t * nbytes);
static
globus_result_t
globus_l_xio_system_try_write(
globus_l_xio_system_t * handle,
globus_off_t offset,
const globus_xio_iovec_t * iov,
int iovc,
int flags,
globus_sockaddr_t * to,
globus_size_t * nbytes);
static
globus_result_t
globus_l_xio_system_close(
int fd);
static
void
globus_l_xio_system_wakeup_handler(
void * user_arg)
{
int rc;
char byte;
GlobusXIOName(globus_l_xio_system_wakeup_handler);
GlobusXIOSystemDebugEnter();
if(!globus_l_xio_system_shutdown_called)
{
byte = 0;
do
{
rc = write(
globus_l_xio_system_wakeup_pipe[1], &byte, sizeof(byte));
} while(rc < 0 && errno == EINTR);
}
GlobusXIOSystemDebugExit();
}
static
int
globus_l_xio_system_activate(void)
{
int i;
char * block;
globus_result_t result;
globus_reltime_t period;
GlobusXIOName(globus_l_xio_system_activate);
if(globus_i_xio_system_common_activate() != GLOBUS_SUCCESS)
{
goto error_activate;
}
GlobusXIOSystemDebugEnter();
globus_cond_init(&globus_l_xio_system_cond, GLOBUS_NULL);
globus_mutex_init(&globus_l_xio_system_fdset_mutex, GLOBUS_NULL);
globus_mutex_init(&globus_l_xio_system_cancel_mutex, GLOBUS_NULL);
globus_l_xio_system_select_active = GLOBUS_FALSE;
globus_l_xio_system_wakeup_pending = GLOBUS_FALSE;
globus_l_xio_system_shutdown_called = GLOBUS_FALSE;
/*
* On some machines (SGI Irix at least), the fd_set structure isn't
* necessarily large enough to hold the maximum number of open file
* descriptors. This ensures that it will be.
*/
globus_l_xio_system_max_fds = GLOBUS_L_OPEN_MAX;
globus_l_xio_system_fd_allocsize = sizeof(fd_set);
if(globus_l_xio_system_fd_allocsize * 8 < globus_l_xio_system_max_fds)
{
/* Conservatively round up to 64 bits */
globus_l_xio_system_fd_allocsize =
((globus_l_xio_system_max_fds + 63) & ~63) / 8;
}
i = globus_l_xio_system_fd_allocsize;
block = (char *) globus_calloc(4, i);
if(!block)
{
goto error_fdsets;
}
globus_l_xio_system_read_fds = (fd_set *) block;
globus_l_xio_system_write_fds = (fd_set *) (block + i * 1);
globus_l_xio_system_ready_reads = (fd_set *) (block + i * 2);
globus_l_xio_system_ready_writes = (fd_set *) (block + i * 3);
globus_l_xio_system_canceled_reads = GLOBUS_NULL;
globus_l_xio_system_canceled_writes = GLOBUS_NULL;
globus_l_xio_system_read_operations = (globus_i_xio_system_op_info_t **)
globus_calloc(
globus_l_xio_system_max_fds * 2,
sizeof(globus_i_xio_system_op_info_t *));
if(!globus_l_xio_system_read_operations)
{
goto error_operations;
}
globus_l_xio_system_write_operations =
globus_l_xio_system_read_operations + globus_l_xio_system_max_fds;
/*
* Create a pipe to myself, so that I can wake up the thread that is
* blocked on a select().
*/
if(pipe(globus_l_xio_system_wakeup_pipe) != 0)
{
goto error_pipe;
}
fcntl(globus_l_xio_system_wakeup_pipe[0], F_SETFD, FD_CLOEXEC);
fcntl(globus_l_xio_system_wakeup_pipe[1], F_SETFD, FD_CLOEXEC);
globus_l_xio_system_highest_fd = globus_l_xio_system_wakeup_pipe[0];
FD_SET(globus_l_xio_system_wakeup_pipe[0], globus_l_xio_system_read_fds);
GlobusTimeReltimeSet(period, 0, 0);
result = globus_callback_register_periodic(
&globus_l_xio_system_poll_handle,
GLOBUS_NULL,
&period,
globus_l_xio_system_poll,
GLOBUS_NULL);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_callback_register_periodic", result);
goto error_register;
}
globus_callback_add_wakeup_handler(
globus_l_xio_system_wakeup_handler, GLOBUS_NULL);
GlobusXIOSystemDebugExit();
return GLOBUS_SUCCESS;
error_register:
globus_l_xio_system_close(globus_l_xio_system_wakeup_pipe[0]);
globus_l_xio_system_close(globus_l_xio_system_wakeup_pipe[1]);
error_pipe:
globus_free(globus_l_xio_system_read_operations);
error_operations:
globus_free(globus_l_xio_system_read_fds);
error_fdsets:
globus_mutex_destroy(&globus_l_xio_system_cancel_mutex);
globus_mutex_destroy(&globus_l_xio_system_fdset_mutex);
globus_cond_destroy(&globus_l_xio_system_cond);
GlobusXIOSystemDebugExitWithError();
globus_i_xio_system_common_deactivate();
error_activate:
return GLOBUS_FAILURE;
}
static
void
globus_l_xio_system_unregister_periodic_cb(
void * user_args)
{
globus_bool_t * signaled;
GlobusXIOName(globus_l_xio_system_unregister_periodic_cb);
GlobusXIOSystemDebugEnter();
signaled = (globus_bool_t *) user_args;
globus_mutex_lock(&globus_l_xio_system_fdset_mutex);
{
*signaled = GLOBUS_TRUE;
globus_cond_signal(&globus_l_xio_system_cond);
}
globus_mutex_unlock(&globus_l_xio_system_fdset_mutex);
GlobusXIOSystemDebugExit();
}
static
int
globus_l_xio_system_deactivate(void)
{
GlobusXIOName(globus_l_xio_system_deactivate);
GlobusXIOSystemDebugEnter();
globus_mutex_lock(&globus_l_xio_system_fdset_mutex);
{
globus_bool_t signaled;
globus_l_xio_system_shutdown_called = GLOBUS_TRUE;
signaled = GLOBUS_FALSE;
globus_callback_unregister(
globus_l_xio_system_poll_handle,
globus_l_xio_system_unregister_periodic_cb,
&signaled,
GLOBUS_NULL);
globus_l_xio_system_wakeup_pending = GLOBUS_TRUE;
globus_l_xio_system_select_wakeup();
while(!signaled)
{
globus_cond_wait(
&globus_l_xio_system_cond, &globus_l_xio_system_fdset_mutex);
}
}
globus_mutex_unlock(&globus_l_xio_system_fdset_mutex);
globus_l_xio_system_close(globus_l_xio_system_wakeup_pipe[0]);
globus_l_xio_system_close(globus_l_xio_system_wakeup_pipe[1]);
globus_list_free(globus_l_xio_system_canceled_reads);
globus_list_free(globus_l_xio_system_canceled_writes);
globus_free(globus_l_xio_system_read_operations);
globus_free(globus_l_xio_system_read_fds);
globus_mutex_destroy(&globus_l_xio_system_cancel_mutex);
globus_mutex_destroy(&globus_l_xio_system_fdset_mutex);
globus_cond_destroy(&globus_l_xio_system_cond);
GlobusXIOSystemDebugExit();
globus_i_xio_system_common_deactivate();
return GLOBUS_SUCCESS;
}
static
globus_result_t
globus_l_xio_system_handle_init(
globus_l_xio_system_t ** u_handle,
int fd,
globus_xio_system_type_t type)
{
globus_l_xio_system_t * handle;
int rc;
globus_result_t result;
GlobusXIOName(globus_l_xio_system_handle_init);
GlobusXIOSystemDebugEnterFD(fd);
handle = (globus_l_xio_system_t *)
globus_malloc(sizeof(globus_l_xio_system_t));
if(!handle)
{
result = GlobusXIOErrorMemory("handle");
goto error_alloc;
}
handle->type = type;
handle->fd = fd;
handle->file_position = globus_xio_system_file_get_position(fd);
rc = globus_l_xio_system_add_nonblocking(handle);
if(rc < 0)
{
result = GlobusXIOErrorSystemError("fcntl", errno);
goto error_fcntl;
}
globus_mutex_init(&handle->lock, NULL);
*u_handle = handle;
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_fcntl:
globus_free(handle);
error_alloc:
*u_handle = GLOBUS_NULL;
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
globus_result_t
globus_xio_system_file_init(
globus_xio_system_file_handle_t * u_handle,
globus_xio_system_file_t fd)
{
return globus_l_xio_system_handle_init(
u_handle, fd, GLOBUS_XIO_SYSTEM_FILE);
}
globus_result_t
globus_xio_system_socket_init(
globus_xio_system_socket_handle_t * u_handle,
globus_xio_system_socket_t fd,
globus_xio_system_type_t type)
{
return globus_l_xio_system_handle_init(u_handle, fd, type);
}
static
void
globus_l_xio_system_handle_destroy(
globus_l_xio_system_t * handle)
{
int fd = handle->fd;
GlobusXIOName(globus_l_xio_system_handle_destroy);
GlobusXIOSystemDebugEnterFD(fd);
globus_l_xio_system_remove_nonblocking(handle);
globus_free(handle);
GlobusXIOSystemDebugExitFD(fd);
}
void
globus_xio_system_file_destroy(
globus_xio_system_file_handle_t handle)
{
globus_l_xio_system_handle_destroy(handle);
}
void
globus_xio_system_socket_destroy(
globus_xio_system_socket_handle_t handle)
{
globus_l_xio_system_handle_destroy(handle);
}
static
void
globus_l_xio_system_cancel_cb(
globus_xio_operation_t op,
void * user_arg,
globus_xio_error_type_t reason)
{
globus_i_xio_system_op_info_t * op_info;
GlobusXIOName(globus_l_xio_system_cancel_cb);
GlobusXIOSystemDebugEnter();
op_info = (globus_i_xio_system_op_info_t *) user_arg;
globus_mutex_lock(&globus_l_xio_system_cancel_mutex);
{
if(op_info->state != GLOBUS_I_XIO_SYSTEM_OP_COMPLETE &&
op_info->state != GLOBUS_I_XIO_SYSTEM_OP_CANCELED)
{
op_info->error = reason == GLOBUS_XIO_ERROR_TIMEOUT
? GlobusXIOErrorObjTimeout()
: GlobusXIOErrorObjCanceled();
globus_mutex_lock(&globus_l_xio_system_fdset_mutex);
{
globus_bool_t pend;
if(op_info->state == GLOBUS_I_XIO_SYSTEM_OP_NEW)
{
op_info->state = GLOBUS_I_XIO_SYSTEM_OP_CANCELED;
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
(_XIOSL("[%s] fd=%d, Canceling NEW\n"),
_xio_name, op_info->handle->fd));
}
else
{
if(globus_l_xio_system_select_active)
{
op_info->state = GLOBUS_I_XIO_SYSTEM_OP_CANCELED;
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
(_XIOSL("[%s] fd=%d, Canceling Active\n"),
_xio_name, op_info->handle->fd));
/* pend the cancel for after select wakes up */
if(!globus_l_xio_system_wakeup_pending)
{
globus_l_xio_system_wakeup_pending = GLOBUS_TRUE;
globus_l_xio_system_select_wakeup();
}
pend = GLOBUS_TRUE;
}
else
{
globus_result_t result;
op_info->state = GLOBUS_I_XIO_SYSTEM_OP_COMPLETE;
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
(_XIOSL("[%s] fd=%d, Canceling Pending\n"),
_xio_name, op_info->handle->fd));
/* unregister and kickout now */
result = globus_callback_register_oneshot(
GLOBUS_NULL,
GLOBUS_NULL,
globus_l_xio_system_kickout,
op_info);
/* really cant do anything else */
if(result != GLOBUS_SUCCESS)
{
globus_panic(
GLOBUS_XIO_SYSTEM_MODULE,
result,
_XIOSL("[%s:%d] Couldn't register callback"),
_xio_name,
__LINE__);
}
pend = GLOBUS_FALSE;
}
/* I can access op_info even though I oneshoted above
* because the CancelDisallow() call in the kickout will
* block until I leave this function
*/
if(op_info->type == GLOBUS_I_XIO_SYSTEM_OP_READ ||
op_info->type == GLOBUS_I_XIO_SYSTEM_OP_ACCEPT)
{
if(pend)
{
globus_list_insert(
&globus_l_xio_system_canceled_reads,
(void *) (intptr_t) op_info->handle->fd);
}
else
{
globus_l_xio_system_unregister_read(
op_info->handle->fd);
}
}
else
{
if(pend)
{
globus_list_insert(
&globus_l_xio_system_canceled_writes,
(void *) (intptr_t) op_info->handle->fd);
}
else
{
globus_l_xio_system_unregister_write(
op_info->handle->fd);
}
}
}
}
globus_mutex_unlock(&globus_l_xio_system_fdset_mutex);
}
}
globus_mutex_unlock(&globus_l_xio_system_cancel_mutex);
GlobusXIOSystemDebugExit();
}
static
globus_result_t
globus_l_xio_system_register_read_fd(
int fd,
globus_i_xio_system_op_info_t * read_info)
{
globus_result_t result;
globus_bool_t do_wakeup = GLOBUS_FALSE;
GlobusXIOName(globus_l_xio_system_register_read_fd);
GlobusXIOSystemDebugEnterFD(fd);
/* I have to do this outside the lock because of lock inversion issues */
if(globus_xio_operation_enable_cancel(
read_info->op, globus_l_xio_system_cancel_cb, read_info))
{
result = GlobusXIOErrorCanceled();
goto error_cancel_enable;
}
globus_mutex_lock(&globus_l_xio_system_fdset_mutex);
{
/* this really shouldnt be possible, but to be thorough ... */
if(read_info->state == GLOBUS_I_XIO_SYSTEM_OP_CANCELED)
{
result = globus_error_put(read_info->error);
goto error_canceled;
}
if(globus_l_xio_system_shutdown_called)
{
result = GlobusXIOErrorNotActivated();
goto error_deactivated;
}
if(fd >= globus_l_xio_system_max_fds)
{
result = GlobusXIOErrorSystemResource(_XIOSL("too many fds"));
goto error_too_many_fds;
}
if(FD_ISSET(fd, globus_l_xio_system_read_fds))
{
result = GlobusXIOErrorAlreadyRegistered();
goto error_already_registered;
}
if(fd > globus_l_xio_system_highest_fd)
{
globus_l_xio_system_highest_fd = fd;
}
FD_SET(fd, globus_l_xio_system_read_fds);
globus_l_xio_system_read_operations[fd] = read_info;
if(globus_l_xio_system_select_active &&
!globus_l_xio_system_wakeup_pending)
{
globus_l_xio_system_wakeup_pending = GLOBUS_TRUE;
do_wakeup = GLOBUS_TRUE;
}
read_info->state = GLOBUS_I_XIO_SYSTEM_OP_PENDING;
}
globus_mutex_unlock(&globus_l_xio_system_fdset_mutex);
if(do_wakeup)
{
/* I do this outside the lock because the select thread is likely
* to wakeup immediately which would mean immediate contention for
* that lock
*/
globus_l_xio_system_select_wakeup();
}
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_already_registered:
error_too_many_fds:
error_deactivated:
error_canceled:
read_info->state = GLOBUS_I_XIO_SYSTEM_OP_COMPLETE;
globus_mutex_unlock(&globus_l_xio_system_fdset_mutex);
globus_xio_operation_disable_cancel(read_info->op);
error_cancel_enable:
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
static
globus_result_t
globus_l_xio_system_register_write_fd(
int fd,
globus_i_xio_system_op_info_t * write_info)
{
globus_result_t result;
globus_bool_t do_wakeup = GLOBUS_FALSE;
GlobusXIOName(globus_l_xio_system_register_write_fd);
GlobusXIOSystemDebugEnterFD(fd);
/* I have to do this outside the lock because of lock inversion issues */
if(globus_xio_operation_enable_cancel(
write_info->op, globus_l_xio_system_cancel_cb, write_info))
{
result = GlobusXIOErrorCanceled();
goto error_cancel_enable;
}
globus_mutex_lock(&globus_l_xio_system_fdset_mutex);
{
/* this really shouldnt be possible, but to be thorough ... */
if(write_info->state == GLOBUS_I_XIO_SYSTEM_OP_CANCELED)
{
result = globus_error_put(write_info->error);
goto error_canceled;
}
if(globus_l_xio_system_shutdown_called)
{
result = GlobusXIOErrorNotActivated();
goto error_deactivated;
}
if(fd >= globus_l_xio_system_max_fds)
{
result = GlobusXIOErrorSystemResource(_XIOSL("too many fds"));
goto error_too_many_fds;
}
if(FD_ISSET(fd, globus_l_xio_system_write_fds))
{
result = GlobusXIOErrorAlreadyRegistered();
goto error_already_registered;
}
if(fd > globus_l_xio_system_highest_fd)
{
globus_l_xio_system_highest_fd = fd;
}
FD_SET(fd, globus_l_xio_system_write_fds);
globus_l_xio_system_write_operations[fd] = write_info;
if(globus_l_xio_system_select_active &&
!globus_l_xio_system_wakeup_pending)
{
globus_l_xio_system_wakeup_pending = GLOBUS_TRUE;
do_wakeup = GLOBUS_TRUE;
}
write_info->state = GLOBUS_I_XIO_SYSTEM_OP_PENDING;
}
globus_mutex_unlock(&globus_l_xio_system_fdset_mutex);
if(do_wakeup)
{
/* I do this outside the lock because the select thread is likely
* to wakeup immediately which would mean immediate contention for
* that lock
*/
globus_l_xio_system_select_wakeup();
}
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_already_registered:
error_too_many_fds:
error_deactivated:
error_canceled:
write_info->state = GLOBUS_I_XIO_SYSTEM_OP_COMPLETE;
globus_mutex_unlock(&globus_l_xio_system_fdset_mutex);
globus_xio_operation_disable_cancel(write_info->op);
error_cancel_enable:
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
/* called locked */
static
void
globus_l_xio_system_unregister_read(
int fd)
{
GlobusXIOName(globus_l_xio_system_unregister_read);
GlobusXIOSystemDebugEnterFD(fd);
globus_assert(FD_ISSET(fd, globus_l_xio_system_read_fds));
FD_CLR(fd, globus_l_xio_system_read_fds);
globus_l_xio_system_read_operations[fd] = GLOBUS_NULL;
GlobusXIOSystemDebugExitFD(fd);
}
/* called locked */
static
void
globus_l_xio_system_unregister_write(
int fd)
{
GlobusXIOName(globus_l_xio_system_unregister_write);
GlobusXIOSystemDebugEnterFD(fd);
globus_assert(FD_ISSET(fd, globus_l_xio_system_write_fds));
FD_CLR(fd, globus_l_xio_system_write_fds);
globus_l_xio_system_write_operations[fd] = GLOBUS_NULL;
GlobusXIOSystemDebugExitFD(fd);
}
static
int
globus_l_xio_system_add_nonblocking(
globus_l_xio_system_t * handle)
{
int flags;
int rc;
flags = fcntl(handle->fd, F_GETFL);
if(flags < 0)
{
rc = flags;
}
else
{
flags |= O_NONBLOCK;
rc = fcntl(handle->fd, F_SETFL, flags);
}
GlobusXIOSystemUpdateErrno();
return rc;
}
static
int
globus_l_xio_system_remove_nonblocking(
globus_l_xio_system_t * handle)
{
int flags;
int rc;
flags = fcntl(handle->fd, F_GETFL);
if(flags < 0)
{
rc = flags;
}
else
{
flags &= ~O_NONBLOCK;
rc = fcntl(handle->fd, F_SETFL, flags);
}
GlobusXIOSystemUpdateErrno();
return rc;
}
static
void
globus_l_xio_system_kickout(
void * user_arg)
{
globus_i_xio_system_op_info_t * op_info;
int fd;
GlobusXIOName(globus_l_xio_system_kickout);
op_info = (globus_i_xio_system_op_info_t *) user_arg;
fd = op_info->handle->fd;
GlobusXIOSystemDebugEnterFD(fd);
globus_xio_operation_disable_cancel(op_info->op);
switch(op_info->type)
{
case GLOBUS_I_XIO_SYSTEM_OP_CONNECT:
case GLOBUS_I_XIO_SYSTEM_OP_ACCEPT:
op_info->sop.non_data.callback(
op_info->error ? globus_error_put(op_info->error) : GLOBUS_SUCCESS,
op_info->user_arg);
break;
default:
op_info->sop.data.callback(
op_info->error ? globus_error_put(op_info->error) : GLOBUS_SUCCESS,
op_info->nbytes,
op_info->user_arg);
GlobusIXIOSystemFreeIovec(
op_info->sop.data.start_iovc,
op_info->sop.data.start_iov);
break;
}
GlobusXIOSystemDebugExitFD(fd);
GlobusIXIOSystemFreeOperation(op_info);
}
static
void
globus_l_xio_system_select_wakeup(void)
{
globus_ssize_t rc;
char byte;
GlobusXIOName(globus_l_xio_system_select_wakeup);
GlobusXIOSystemDebugEnter();
byte = 0;
do
{
rc = write(globus_l_xio_system_wakeup_pipe[1], &byte, sizeof(byte));
} while(rc < 0 && errno == EINTR);
if(rc <= 0)
{
globus_panic(
GLOBUS_XIO_SYSTEM_MODULE,
GlobusXIOErrorSystemError("write", errno),
_XIOSL("[%s:%d] Couldn't wakeup select"),
_xio_name,
__LINE__);
}
GlobusXIOSystemDebugExit();
}
static
void
globus_l_xio_system_handle_wakeup(void)
{
char buf[64];
globus_ssize_t done;
GlobusXIOName(globus_l_xio_system_handle_wakeup);
GlobusXIOSystemDebugEnter();
do
{
done = read(globus_l_xio_system_wakeup_pipe[0], buf, sizeof(buf));
} while(done < 0 && errno == EINTR);
GlobusXIOSystemDebugExit();
}
static
globus_bool_t
globus_l_xio_system_handle_read(
int fd)
{
globus_bool_t handled_it;
globus_i_xio_system_op_info_t * read_info;
globus_size_t nbytes;
globus_result_t result;
GlobusXIOName(globus_l_xio_system_handle_read);
GlobusXIOSystemDebugEnterFD(fd);
handled_it = GLOBUS_FALSE;
read_info = globus_l_xio_system_read_operations[fd];
result = GLOBUS_SUCCESS;
globus_xio_operation_refresh_timeout(read_info->op);
if(read_info->state == GLOBUS_I_XIO_SYSTEM_OP_CANCELED)
{
/* error already set on info */
goto error_canceled;
}
switch(read_info->type)
{
case GLOBUS_I_XIO_SYSTEM_OP_ACCEPT:
{
int new_fd;
do
{
new_fd = accept(fd, GLOBUS_NULL, GLOBUS_NULL);
GlobusXIOSystemUpdateErrno();
} while(new_fd < 0 && errno == EINTR);
if(new_fd < 0)
{
if(errno != ECONNABORTED &&
errno != EAGAIN && errno != EWOULDBLOCK)
{
result = GlobusXIOErrorSystemError("accept", errno);
}
}
else
{
int rc;
globus_l_xio_system_t tmp_handle;
*read_info->sop.non_data.out_fd = new_fd;
tmp_handle.fd = new_fd;
tmp_handle.type = GLOBUS_XIO_SYSTEM_TCP;
rc = globus_l_xio_system_remove_nonblocking(&tmp_handle);
read_info->nbytes++;
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
(_XIOSL("[%s] Accepted new connection, fd=%d\n"),
_xio_name, new_fd));
}
}
break;
case GLOBUS_I_XIO_SYSTEM_OP_READ:
result = globus_l_xio_system_try_read(
read_info->handle,
read_info->offset,
read_info->sop.data.iov,
read_info->sop.data.iovc,
read_info->sop.data.flags,
read_info->sop.data.addr,
&nbytes);
if(result == GLOBUS_SUCCESS)
{
read_info->nbytes += nbytes;
read_info->offset += nbytes;
GlobusIXIOUtilAdjustIovec(
read_info->sop.data.iov, read_info->sop.data.iovc, nbytes);
}
break;
default:
globus_assert(0 && "Unexpected type for read operation");
return GLOBUS_FALSE;
break;
}
if(result != GLOBUS_SUCCESS)
{
read_info->error = globus_error_get(result);
}
/* always true for accept operations */
if(read_info->nbytes >= read_info->waitforbytes ||
result != GLOBUS_SUCCESS)
{
error_canceled:
handled_it = GLOBUS_TRUE;
read_info->state = GLOBUS_I_XIO_SYSTEM_OP_COMPLETE;
globus_mutex_lock(&globus_l_xio_system_fdset_mutex);
{
globus_l_xio_system_unregister_read(fd);
}
globus_mutex_unlock(&globus_l_xio_system_fdset_mutex);
result = globus_callback_register_oneshot(
GLOBUS_NULL, GLOBUS_NULL, globus_l_xio_system_kickout, read_info);
/* really cant do anything else */
if(result != GLOBUS_SUCCESS)
{
globus_panic(
GLOBUS_XIO_SYSTEM_MODULE,
result,
_XIOSL("[%s:%d] Couldn't register callback"),
_xio_name,
__LINE__);
}
}
GlobusXIOSystemDebugExitFD(fd);
return handled_it;
}
static
globus_bool_t
globus_l_xio_system_handle_write(
int fd)
{
globus_bool_t handled_it;
globus_i_xio_system_op_info_t * write_info;
globus_size_t nbytes;
globus_result_t result;
GlobusXIOName(globus_l_xio_system_handle_write);
GlobusXIOSystemDebugEnterFD(fd);
handled_it = GLOBUS_FALSE;
result = GLOBUS_SUCCESS;
write_info = globus_l_xio_system_write_operations[fd];
globus_xio_operation_refresh_timeout(write_info->op);
if(write_info->state == GLOBUS_I_XIO_SYSTEM_OP_CANCELED)
{
/* error already set on info */
goto error_canceled;
}
switch(write_info->type)
{
case GLOBUS_I_XIO_SYSTEM_OP_CONNECT:
{
int err;
globus_socklen_t errlen;
errlen = sizeof(err);
if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) < 0)
{
GlobusXIOSystemUpdateErrno();
err = errno;
}
if(err)
{
result = GlobusXIOErrorSystemError("connect", err);
}
}
break;
case GLOBUS_I_XIO_SYSTEM_OP_WRITE:
result = globus_l_xio_system_try_write(
write_info->handle,
write_info->offset,
write_info->sop.data.iov,
write_info->sop.data.iovc,
write_info->sop.data.flags,
write_info->sop.data.addr,
&nbytes);
if(result == GLOBUS_SUCCESS)
{
write_info->nbytes += nbytes;
write_info->offset += nbytes;
GlobusIXIOUtilAdjustIovec(
write_info->sop.data.iov, write_info->sop.data.iovc, nbytes);
}
break;
default:
globus_assert(0 && "Unexpected type for write operation");
return GLOBUS_FALSE;
break;
}
if(result != GLOBUS_SUCCESS)
{
write_info->error = globus_error_get(result);
}
/* always true for connect operations */
if(write_info->nbytes >= write_info->waitforbytes ||
result != GLOBUS_SUCCESS)
{
error_canceled:
handled_it = GLOBUS_TRUE;
write_info->state = GLOBUS_I_XIO_SYSTEM_OP_COMPLETE;
globus_mutex_lock(&globus_l_xio_system_fdset_mutex);
{
globus_l_xio_system_unregister_write(fd);
}
globus_mutex_unlock(&globus_l_xio_system_fdset_mutex);
result = globus_callback_register_oneshot(
GLOBUS_NULL, GLOBUS_NULL, globus_l_xio_system_kickout, write_info);
/* really cant do anything else */
if(result != GLOBUS_SUCCESS)
{
globus_panic(
GLOBUS_XIO_SYSTEM_MODULE,
result,
_XIOSL("[%s:%d] Couldn't register callback"),
_xio_name,
__LINE__);
}
}
GlobusXIOSystemDebugExitFD(fd);
return handled_it;
}
/*
* one of these fds is bad, lock down the fdset and check them all
* --- assumed to be called with cancel lock held after a select
*/
static
void
globus_l_xio_system_bad_apple(void)
{
globus_i_xio_system_op_info_t * op_info;
int fd;
int rc;
struct stat stat_buf;
GlobusXIOName(globus_l_xio_system_bad_apple);
GlobusXIOSystemDebugEnter();
globus_mutex_lock(&globus_l_xio_system_fdset_mutex);
{
for(fd = 0; fd <= globus_l_xio_system_highest_fd; fd++)
{
if(FD_ISSET(fd, globus_l_xio_system_read_fds))
{
rc = fstat(fd, &stat_buf);
GlobusXIOSystemUpdateErrno();
if(rc < 0 && errno == EBADF)
{
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
(_XIOSL("[%s] fd=%d, Canceling read bad apple\n"),
_xio_name, fd));
op_info = globus_l_xio_system_read_operations[fd];
if(op_info->state == GLOBUS_I_XIO_SYSTEM_OP_PENDING)
{
op_info->state = GLOBUS_I_XIO_SYSTEM_OP_CANCELED;
op_info->error = GlobusXIOErrorObjParameter("handle");
globus_list_insert(
&globus_l_xio_system_canceled_reads,
(void *) (intptr_t) fd);
}
}
}
if(FD_ISSET(fd, globus_l_xio_system_write_fds))
{
rc = fstat(fd, &stat_buf);
GlobusXIOSystemUpdateErrno();
if(rc < 0 && errno == EBADF)
{
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
(_XIOSL("[%s] fd=%d, Canceling write bad apple\n"),
_xio_name, fd));
op_info = globus_l_xio_system_write_operations[fd];
if(op_info->state == GLOBUS_I_XIO_SYSTEM_OP_PENDING)
{
op_info->state = GLOBUS_I_XIO_SYSTEM_OP_CANCELED;
op_info->error = GlobusXIOErrorObjParameter("handle");
globus_list_insert(
&globus_l_xio_system_canceled_writes,
(void *) (intptr_t) fd);
}
}
}
}
}
globus_mutex_unlock(&globus_l_xio_system_fdset_mutex);
GlobusXIOSystemDebugExit();
}
static
void
globus_l_xio_system_poll(
void * user_args)
{
globus_bool_t time_left_is_zero;
globus_bool_t handled_something;
GlobusXIOName(globus_l_xio_system_poll);
GlobusXIOSystemDebugEnter();
handled_something = GLOBUS_FALSE;
do
{
globus_reltime_t time_left;
globus_bool_t time_left_is_infinity;
int num;
int nready;
int fd;
int save_errno;
time_left_is_zero = GLOBUS_FALSE;
time_left_is_infinity = GLOBUS_FALSE;
globus_callback_get_timeout(&time_left);
if(globus_reltime_cmp(&time_left, &globus_i_reltime_zero) == 0)
{
time_left_is_zero = GLOBUS_TRUE;
}
else if(globus_time_reltime_is_infinity(&time_left))
{
time_left_is_infinity = GLOBUS_TRUE;
}
globus_mutex_lock(&globus_l_xio_system_fdset_mutex);
{
memcpy(
globus_l_xio_system_ready_reads,
globus_l_xio_system_read_fds,
globus_l_xio_system_fd_allocsize);
memcpy(
globus_l_xio_system_ready_writes,
globus_l_xio_system_write_fds,
globus_l_xio_system_fd_allocsize);
num = globus_l_xio_system_highest_fd + 1;
globus_l_xio_system_select_active = GLOBUS_TRUE;
}
globus_mutex_unlock(&globus_l_xio_system_fdset_mutex);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
(_XIOSL("[%s] Before select\n"), _xio_name));
nready = select(
num,
globus_l_xio_system_ready_reads,
globus_l_xio_system_ready_writes,
GLOBUS_NULL,
(time_left_is_infinity ? GLOBUS_NULL : &time_left));
GlobusXIOSystemUpdateErrno();
save_errno = errno;
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
(_XIOSL("[%s] After select\n"), _xio_name));
globus_mutex_lock(&globus_l_xio_system_cancel_mutex);
{
globus_l_xio_system_select_active = GLOBUS_FALSE;
if(nready > 0)
{
fd = globus_l_xio_system_wakeup_pipe[0];
if(FD_ISSET(fd, globus_l_xio_system_ready_reads))
{
globus_l_xio_system_handle_wakeup();
globus_l_xio_system_wakeup_pending = GLOBUS_FALSE;
FD_CLR(fd, globus_l_xio_system_ready_reads);
nready--;
}
}
else
if(nready == 0)
{
time_left_is_zero = GLOBUS_TRUE;
}
else
{
if(save_errno == EBADF)
{
globus_l_xio_system_bad_apple();
}
/*
* can't really do anything about other errors
* so, set ready fds to known state in case there are things
* to be canceled
*/
nready = 0;
memset(
globus_l_xio_system_ready_reads,
0,
globus_l_xio_system_fd_allocsize);
memset(
globus_l_xio_system_ready_writes,
0,
globus_l_xio_system_fd_allocsize);
}
while(!globus_list_empty(globus_l_xio_system_canceled_reads))
{
fd = (int) (intptr_t) globus_list_remove(
&globus_l_xio_system_canceled_reads,
globus_l_xio_system_canceled_reads);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
(_XIOSL("[%s] fd=%d, Setting canceled read\n"), _xio_name, fd));
if(!FD_ISSET(fd, globus_l_xio_system_ready_reads))
{
FD_SET(fd, globus_l_xio_system_ready_reads);
nready++;
}
}
while(!globus_list_empty(globus_l_xio_system_canceled_writes))
{
fd = (int) (intptr_t) globus_list_remove(
&globus_l_xio_system_canceled_writes,
globus_l_xio_system_canceled_writes);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
(_XIOSL("[%s] fd=%d, Setting canceled read\n"), _xio_name, fd));
if(!FD_ISSET(fd, globus_l_xio_system_ready_writes))
{
FD_SET(fd, globus_l_xio_system_ready_writes);
nready++;
}
}
for(fd = 0; nready; fd++)
{
if(FD_ISSET(fd, globus_l_xio_system_ready_reads))
{
nready--;
if(globus_l_xio_system_handle_read(fd))
{
handled_something = GLOBUS_TRUE;
}
}
if(FD_ISSET(fd, globus_l_xio_system_ready_writes))
{
nready--;
if(globus_l_xio_system_handle_write(fd))
{
handled_something = GLOBUS_TRUE;
}
}
}
}
globus_mutex_unlock(&globus_l_xio_system_cancel_mutex);
} while(!handled_something &&
!time_left_is_zero &&
!globus_l_xio_system_shutdown_called);
GlobusXIOSystemDebugExit();
}
globus_result_t
globus_xio_system_socket_register_connect(
globus_xio_operation_t op,
globus_xio_system_socket_handle_t handle,
globus_sockaddr_t * addr,
globus_xio_system_callback_t callback,
void * user_arg)
{
globus_bool_t done;
globus_result_t result;
globus_i_xio_system_op_info_t * op_info;
int fd = handle->fd;
GlobusXIOName(globus_xio_system_socket_register_connect);
GlobusXIOSystemDebugEnterFD(fd);
done = GLOBUS_FALSE;
while(!done && connect(
fd, (const struct sockaddr *) addr, GlobusLibcSockaddrLen(addr)) < 0)
{
GlobusXIOSystemUpdateErrno();
switch(errno)
{
case EINPROGRESS:
done = GLOBUS_TRUE;
break;
case EINTR:
/* retry */
break;
case ETIMEDOUT: /* this was in globus io.. not sure why */
globus_thread_yield();
break;
default:
result = GlobusXIOErrorSystemError("connect", errno);
goto error_connect;
}
}
GlobusIXIOSystemAllocOperation(op_info);
if(!op_info)
{
result = GlobusXIOErrorMemory("op_info");
goto error_op_info;
}
op_info->type = GLOBUS_I_XIO_SYSTEM_OP_CONNECT;
op_info->state = GLOBUS_I_XIO_SYSTEM_OP_NEW;
op_info->op = op;
op_info->handle = handle;
op_info->user_arg = user_arg;
op_info->sop.non_data.callback = callback;
result = globus_l_xio_system_register_write_fd(fd, op_info);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
_XIOSL("globus_l_xio_system_register_write_fd"), result);
goto error_register;
}
/* handle could be destroyed by time we get here - no touch! */
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_register:
GlobusIXIOSystemFreeOperation(op_info);
error_op_info:
error_connect:
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
globus_result_t
globus_xio_system_socket_register_accept(
globus_xio_operation_t op,
globus_xio_system_socket_handle_t listener_handle,
globus_xio_system_socket_t * out_fd,
globus_xio_system_callback_t callback,
void * user_arg)
{
globus_result_t result;
globus_i_xio_system_op_info_t * op_info;
int fd = listener_handle->fd;
GlobusXIOName(globus_xio_system_socket_register_accept);
GlobusXIOSystemDebugEnterFD(fd);
GlobusIXIOSystemAllocOperation(op_info);
if(!op_info)
{
result = GlobusXIOErrorMemory("op_info");
goto error_op_info;
}
op_info->type = GLOBUS_I_XIO_SYSTEM_OP_ACCEPT;
op_info->state = GLOBUS_I_XIO_SYSTEM_OP_NEW;
op_info->op = op;
op_info->handle = listener_handle;
op_info->user_arg = user_arg;
op_info->sop.non_data.callback = callback;
op_info->sop.non_data.out_fd = out_fd;
op_info->waitforbytes = 1;
result = globus_l_xio_system_register_read_fd(fd, op_info);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
_XIOSL("globus_l_xio_system_register_read_fd"), result);
goto error_register;
}
/* handle could be destroyed by time we get here - no touch! */
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_register:
GlobusIXIOSystemFreeOperation(op_info);
error_op_info:
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
static
globus_result_t
globus_l_xio_system_register_read(
globus_xio_operation_t op,
globus_l_xio_system_t * handle,
globus_off_t offset,
const globus_xio_iovec_t * u_iov,
int u_iovc,
globus_size_t waitforbytes,
int flags,
globus_sockaddr_t * from,
globus_xio_system_data_callback_t callback,
void * user_arg)
{
globus_result_t result;
globus_i_xio_system_op_info_t * op_info;
struct iovec * iov;
int fd = handle->fd;
GlobusXIOName(globus_l_xio_system_register_read);
GlobusXIOSystemDebugEnterFD(fd);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
(_XIOSL("[%s] Waiting for %u bytes\n"), _xio_name, (unsigned) waitforbytes));
GlobusIXIOSystemAllocOperation(op_info);
if(!op_info)
{
result = GlobusXIOErrorMemory("op_info");
goto error_op_info;
}
GlobusIXIOSystemAllocIovec(u_iovc, iov);
if(!iov)
{
result = GlobusXIOErrorMemory("iov");
goto error_iovec;
}
GlobusIXIOUtilTransferIovec(iov, u_iov, u_iovc);
op_info->type = GLOBUS_I_XIO_SYSTEM_OP_READ;
op_info->sop.data.start_iov = iov;
op_info->sop.data.start_iovc = u_iovc;
op_info->sop.data.iov = iov;
op_info->sop.data.iovc = u_iovc;
op_info->sop.data.addr = from;
op_info->sop.data.flags = flags;
op_info->state = GLOBUS_I_XIO_SYSTEM_OP_NEW;
op_info->op = op;
op_info->handle = handle;
op_info->user_arg = user_arg;
op_info->sop.data.callback = callback;
op_info->waitforbytes = waitforbytes;
op_info->offset = offset;
result = globus_l_xio_system_register_read_fd(fd, op_info);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_l_xio_system_register_read_fd", result);
goto error_register;
}
/* handle could be destroyed by time we get here - no touch! */
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_register:
GlobusIXIOSystemFreeIovec(u_iovc, iov);
error_iovec:
GlobusIXIOSystemFreeOperation(op_info);
error_op_info:
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
globus_result_t
globus_xio_system_file_register_read(
globus_xio_operation_t op,
globus_xio_system_file_handle_t handle,
globus_off_t offset,
const globus_xio_iovec_t * u_iov,
int u_iovc,
globus_size_t waitforbytes,
globus_xio_system_data_callback_t callback,
void * user_arg)
{
return globus_l_xio_system_register_read(
op,
handle,
offset,
u_iov,
u_iovc,
waitforbytes,
0,
GLOBUS_NULL,
callback,
user_arg);
}
globus_result_t
globus_xio_system_socket_register_read(
globus_xio_operation_t op,
globus_xio_system_socket_handle_t handle,
const globus_xio_iovec_t * u_iov,
int u_iovc,
globus_size_t waitforbytes,
int flags,
globus_sockaddr_t * from,
globus_xio_system_data_callback_t callback,
void * user_arg)
{
return globus_l_xio_system_register_read(
op,
handle,
-1,
u_iov,
u_iovc,
waitforbytes,
flags,
from,
callback,
user_arg);
}
static
globus_result_t
globus_l_xio_system_register_write(
globus_xio_operation_t op,
globus_l_xio_system_t * handle,
globus_off_t offset,
const globus_xio_iovec_t * u_iov,
int u_iovc,
globus_size_t waitforbytes,
int flags,
globus_sockaddr_t * to,
globus_xio_system_data_callback_t callback,
void * user_arg)
{
globus_result_t result;
globus_i_xio_system_op_info_t * op_info;
struct iovec * iov;
int fd = handle->fd;
GlobusXIOName(globus_l_xio_system_register_write);
GlobusXIOSystemDebugEnterFD(fd);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
(_XIOSL("[%s] Waiting for %u bytes\n"), _xio_name, (unsigned) waitforbytes));
GlobusIXIOSystemAllocOperation(op_info);
if(!op_info)
{
result = GlobusXIOErrorMemory("op_info");
goto error_op_info;
}
GlobusIXIOSystemAllocIovec(u_iovc, iov);
if(!iov)
{
result = GlobusXIOErrorMemory("iov");
goto error_iovec;
}
GlobusIXIOUtilTransferIovec(iov, u_iov, u_iovc);
op_info->type = GLOBUS_I_XIO_SYSTEM_OP_WRITE;
op_info->sop.data.start_iov = iov;
op_info->sop.data.start_iovc = u_iovc;
op_info->sop.data.iov = iov;
op_info->sop.data.iovc = u_iovc;
op_info->sop.data.addr = to;
op_info->sop.data.flags = flags;
op_info->state = GLOBUS_I_XIO_SYSTEM_OP_NEW;
op_info->op = op;
op_info->handle = handle;
op_info->user_arg = user_arg;
op_info->sop.data.callback = callback;
op_info->waitforbytes = waitforbytes;
op_info->offset = offset;
result = globus_l_xio_system_register_write_fd(fd, op_info);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_l_xio_system_register_write_fd", result);
goto error_register;
}
/* handle could be destroyed by time we get here - no touch! */
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_register:
GlobusIXIOSystemFreeIovec(u_iovc, iov);
error_iovec:
GlobusIXIOSystemFreeOperation(op_info);
error_op_info:
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
globus_result_t
globus_xio_system_file_register_write(
globus_xio_operation_t op,
globus_xio_system_file_handle_t handle,
globus_off_t offset,
const globus_xio_iovec_t * u_iov,
int u_iovc,
globus_size_t waitforbytes,
globus_xio_system_data_callback_t callback,
void * user_arg)
{
return globus_l_xio_system_register_write(
op,
handle,
offset,
u_iov,
u_iovc,
waitforbytes,
0,
GLOBUS_NULL,
callback,
user_arg);
}
globus_result_t
globus_xio_system_socket_register_write(
globus_xio_operation_t op,
globus_xio_system_socket_handle_t handle,
const globus_xio_iovec_t * u_iov,
int u_iovc,
globus_size_t waitforbytes,
int flags,
globus_sockaddr_t * to,
globus_xio_system_data_callback_t callback,
void * user_arg)
{
return globus_l_xio_system_register_write(
op,
handle,
-1,
u_iov,
u_iovc,
waitforbytes,
flags,
to,
callback,
user_arg);
}
static
globus_result_t
globus_l_xio_system_try_read(
globus_l_xio_system_t * handle,
globus_off_t offset,
const globus_xio_iovec_t * iov,
int iovc,
int flags,
globus_sockaddr_t * from,
globus_size_t * nbytes)
{
if(handle->type == GLOBUS_XIO_SYSTEM_FILE)
{
globus_result_t result;
globus_mutex_lock(&handle->lock);
{
if(handle->file_position != offset &&
(iovc > 1 || iov->iov_len > 0)) /* else select() mode */
{
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[globus_l_xio_system_try_read] fd=%d, "
"Changing file position to %" GLOBUS_OFF_T_FORMAT "\n",
handle->fd, offset));
/* assume success as possible failures are ignorable */
lseek(handle->fd, offset, SEEK_SET);
handle->file_position = offset;
}
result = globus_i_xio_system_file_try_read(
handle->fd, iov, iovc, nbytes);
handle->file_position += *nbytes;
}
globus_mutex_unlock(&handle->lock);
return result;
}
else
{
return globus_i_xio_system_socket_try_read(
handle->fd, iov, iovc, flags, from, nbytes);
}
}
static
globus_result_t
globus_l_xio_system_read(
globus_l_xio_system_t * handle,
globus_off_t offset,
const globus_xio_iovec_t * u_iov,
int u_iovc,
globus_size_t waitforbytes,
int flags,
globus_sockaddr_t * from,
globus_size_t * u_nbytes)
{
globus_result_t result;
int rc;
GlobusXIOName(globus_l_xio_system_read);
GlobusXIOSystemDebugEnter();
result = globus_l_xio_system_try_read(
handle, offset, u_iov, u_iovc, flags, from, u_nbytes);
if(result == GLOBUS_SUCCESS && *u_nbytes < waitforbytes)
{
struct iovec * iov;
int iovc;
globus_size_t nbytes = *u_nbytes;
globus_size_t total = nbytes;
/*
* XXX this is not thread safe... both reads and writes are mucking
* with blocking status.
* worst case, we read 0 bytes in the loop below, return, and xio
* calls us again to finish up.
*/
rc = globus_l_xio_system_remove_nonblocking(handle);
GlobusIXIOSystemAllocIovec(u_iovc, iov);
if(!iov)
{
result = GlobusXIOErrorMemory("iov");
goto error_iovec;
}
GlobusIXIOUtilTransferIovec(iov, u_iov, u_iovc);
u_iov = iov;
iovc = u_iovc;
do
{
if(total > 0)
{
/* only capture source first time around */
from = GLOBUS_NULL;
}
offset += nbytes;
GlobusIXIOUtilAdjustIovec(iov, iovc, nbytes);
result = globus_l_xio_system_try_read(
handle, offset, iov, iovc, flags, from, &nbytes);
total += nbytes;
} while(result == GLOBUS_SUCCESS && nbytes && total < waitforbytes);
*u_nbytes = total;
GlobusIXIOSystemFreeIovec(u_iovc, (globus_xio_iovec_t *) u_iov);
rc = globus_l_xio_system_add_nonblocking(handle);
}
GlobusXIOSystemDebugExit();
return result;
error_iovec:
rc = globus_l_xio_system_add_nonblocking(handle);
GlobusXIOSystemDebugExitWithError();
return result;
}
globus_result_t
globus_xio_system_file_read(
globus_xio_system_file_handle_t handle,
globus_off_t offset,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t waitforbytes,
globus_size_t * nbytes)
{
return globus_l_xio_system_read(
handle, offset, iov, iovc, waitforbytes, 0, GLOBUS_NULL, nbytes);
}
globus_result_t
globus_xio_system_socket_read(
globus_xio_system_socket_handle_t handle,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t waitforbytes,
int flags,
globus_sockaddr_t * from,
globus_size_t * nbytes)
{
return globus_l_xio_system_read(
handle, -1, iov, iovc, waitforbytes, flags, from, nbytes);
}
static
globus_result_t
globus_l_xio_system_try_write(
globus_l_xio_system_t * handle,
globus_off_t offset,
const globus_xio_iovec_t * iov,
int iovc,
int flags,
globus_sockaddr_t * to,
globus_size_t * nbytes)
{
if(handle->type == GLOBUS_XIO_SYSTEM_FILE)
{
globus_result_t result;
globus_mutex_lock(&handle->lock);
{
if(handle->file_position != offset &&
(iovc > 1 || iov->iov_len > 0)) /* else select() mode */
{
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[globus_l_xio_system_try_write] fd=%d, "
"Changing file position to %" GLOBUS_OFF_T_FORMAT "\n",
handle->fd, offset));
/* assume success as possible failures are ignorable */
lseek(handle->fd, offset, SEEK_SET);
handle->file_position = offset;
}
result = globus_i_xio_system_file_try_write(
handle->fd, iov, iovc, nbytes);
handle->file_position += *nbytes;
}
globus_mutex_unlock(&handle->lock);
return result;
}
else
{
return globus_i_xio_system_socket_try_write(
handle->fd, iov, iovc, flags, to, nbytes);
}
}
static
globus_result_t
globus_l_xio_system_write(
globus_l_xio_system_t * handle,
globus_off_t offset,
const globus_xio_iovec_t * u_iov,
int u_iovc,
globus_size_t waitforbytes,
int flags,
globus_sockaddr_t * to,
globus_size_t * u_nbytes)
{
globus_result_t result;
int rc;
GlobusXIOName(globus_l_xio_system_write);
GlobusXIOSystemDebugEnter();
result = globus_l_xio_system_try_write(
handle, offset, u_iov, u_iovc, flags, to, u_nbytes);
if(result == GLOBUS_SUCCESS && *u_nbytes < waitforbytes)
{
struct iovec * iov;
int iovc;
globus_size_t nbytes = *u_nbytes;
globus_size_t total = nbytes;
/*
* XXX this is not thread safe... both reads and writes are mucking
* with blocking status
*/
rc = globus_l_xio_system_remove_nonblocking(handle);
GlobusIXIOSystemAllocIovec(u_iovc, iov);
if(!iov)
{
result = GlobusXIOErrorMemory("iov");
goto error_iovec;
}
GlobusIXIOUtilTransferIovec(iov, u_iov, u_iovc);
u_iov = iov;
iovc = u_iovc;
do
{
offset += nbytes;
GlobusIXIOUtilAdjustIovec(iov, iovc, nbytes);
result = globus_l_xio_system_try_write(
handle, offset, iov, iovc, flags, to, &nbytes);
total += nbytes;
} while(result == GLOBUS_SUCCESS && nbytes && total < waitforbytes);
*u_nbytes = total;
GlobusIXIOSystemFreeIovec(u_iovc, (globus_xio_iovec_t *) u_iov);
rc = globus_l_xio_system_add_nonblocking(handle);
}
GlobusXIOSystemDebugExit();
return result;
error_iovec:
rc = globus_l_xio_system_add_nonblocking(handle);
GlobusXIOSystemDebugExitWithError();
return result;
}
globus_result_t
globus_xio_system_file_write(
globus_xio_system_file_handle_t handle,
globus_off_t offset,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t waitforbytes,
globus_size_t * nbytes)
{
return globus_l_xio_system_write(
handle, offset, iov, iovc, waitforbytes, 0, GLOBUS_NULL, nbytes);
}
globus_result_t
globus_xio_system_socket_write(
globus_xio_system_socket_handle_t handle,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t waitforbytes,
int flags,
globus_sockaddr_t * to,
globus_size_t * nbytes)
{
return globus_l_xio_system_write(
handle, -1, iov, iovc, waitforbytes, flags, to, nbytes);
}
static
globus_result_t
globus_l_xio_system_close(
int fd)
{
globus_result_t result;
int rc;
GlobusXIOName(globus_l_xio_system_close);
GlobusXIOSystemDebugEnterFD(fd);
do
{
rc = close(fd);
GlobusXIOSystemUpdateErrno();
} while(rc < 0 && errno == EINTR);
if(rc < 0)
{
result = GlobusXIOErrorSystemError("close", errno);
goto error_close;
}
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_close:
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
globus_off_t
globus_xio_system_file_get_position(
globus_xio_system_file_t fd)
{
globus_off_t offset;
GlobusXIOName(globus_xio_system_file_get_position);
GlobusXIOSystemDebugEnterFD(fd);
/* ignore errors, may be a pipe or other unseekable */
offset = lseek(fd, 0, SEEK_CUR);
if(offset == -1)
{
offset = 0;
}
GlobusXIOSystemDebugExitFD(fd);
return offset;
}
globus_off_t
globus_xio_system_file_get_size(
globus_xio_system_file_t fd)
{
globus_off_t size = -1;
struct stat buf;
GlobusXIOName(globus_xio_system_file_get_size);
GlobusXIOSystemDebugEnterFD(fd);
if(fstat(fd, &buf) == 0)
{
size = buf.st_size;
}
GlobusXIOSystemDebugExitFD(fd);
return size;
}
globus_xio_system_file_t
globus_xio_system_convert_stdio(
const char * stdio)
{
if(strcmp(stdio, "stdin") == 0)
{
return fileno(stdin);
}
else if(strcmp(stdio, "stdout") == 0)
{
return fileno(stdout);
}
else if(strcmp(stdio, "stderr") == 0)
{
return fileno(stderr);
}
return GLOBUS_XIO_SYSTEM_INVALID_FILE;
}
globus_result_t
globus_xio_system_file_truncate(
globus_xio_system_file_t fd,
globus_off_t size)
{
globus_result_t result;
int rc;
GlobusXIOName(globus_xio_system_file_truncate);
GlobusXIOSystemDebugEnterFD(fd);
#ifdef TARGET_ARCH_ARM
setErrno(EINVAL);
result = GlobusXIOErrorSystemError("ftruncate", errno);
#else
rc = ftruncate(fd, size);
if(rc < 0)
{
GlobusXIOSystemUpdateErrno();
result = GlobusXIOErrorSystemError("ftruncate", errno);
goto error_truncate;
}
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_truncate:
#endif
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
globus_result_t
globus_xio_system_file_open(
globus_xio_system_file_t * fd,
const char * filename,
int flags,
unsigned long mode)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_file_open);
*fd = -1;
GlobusXIOSystemDebugEnterFD(*fd);
do
{
*fd = open(filename, flags, mode);
GlobusXIOSystemUpdateErrno();
} while(*fd < 0 && errno == EINTR);
if(*fd < 0)
{
result = GlobusXIOErrorSystemError("open", errno);
goto error_open;
}
/* all handles created by me are closed on exec */
fcntl(*fd, F_SETFD, FD_CLOEXEC);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[%s] Opened file, %s fd=%d\n", _xio_name, filename, *fd));
GlobusXIOSystemDebugExitFD(*fd);
return GLOBUS_SUCCESS;
error_open:
GlobusXIOSystemDebugExitWithErrorFD(*fd);
return result;
}
globus_result_t
globus_xio_system_file_close(
globus_xio_system_file_t fd)
{
return globus_l_xio_system_close(fd);
}
globus_result_t
globus_xio_system_socket_create(
globus_xio_system_socket_t * fd,
int domain,
int type,
int protocol)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_socket_create);
*fd = -1;
GlobusXIOSystemDebugEnterFD(*fd);
*fd = socket(domain, type, protocol);
GlobusXIOSystemUpdateErrno();
if(*fd == -1)
{
result = GlobusXIOErrorSystemError("socket", errno);
goto error_socket;
}
/* all handles created by me are closed on exec */
fcntl(*fd, F_SETFD, FD_CLOEXEC);
GlobusXIOSystemDebugExitFD(*fd);
return GLOBUS_SUCCESS;
error_socket:
GlobusXIOSystemDebugExitWithErrorFD(*fd);
return result;
}
globus_result_t
globus_xio_system_socket_setsockopt(
globus_xio_system_socket_t socket,
int level,
int optname,
const void * optval,
globus_socklen_t optlen)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_socket_setsockopt);
GlobusXIOSystemDebugEnterFD(socket);
if(setsockopt(socket, level, optname, (void *) optval, optlen) < 0)
{
GlobusXIOSystemUpdateErrno();
result = GlobusXIOErrorSystemError("setsockopt", errno);
goto error_setsockopt;
}
GlobusXIOSystemDebugExitFD(socket);
return GLOBUS_SUCCESS;
error_setsockopt:
GlobusXIOSystemDebugExitWithErrorFD(socket);
return result;
}
globus_result_t
globus_xio_system_socket_getsockopt(
globus_xio_system_socket_t socket,
int level,
int optname,
void * optval,
globus_socklen_t * optlen)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_socket_getsockopt);
GlobusXIOSystemDebugEnterFD(socket);
if(getsockopt(socket, level, optname, optval, optlen) < 0)
{
GlobusXIOSystemUpdateErrno();
result = GlobusXIOErrorSystemError("getsockopt", errno);
goto error_getsockopt;
}
GlobusXIOSystemDebugExitFD(socket);
return GLOBUS_SUCCESS;
error_getsockopt:
GlobusXIOSystemDebugExitWithErrorFD(socket);
return result;
}
globus_result_t
globus_xio_system_socket_getsockname(
globus_xio_system_socket_t socket,
struct sockaddr * name,
globus_socklen_t * namelen)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_socket_getsockname);
GlobusXIOSystemDebugEnterFD(socket);
if(getsockname(socket, name, namelen) < 0)
{
GlobusXIOSystemUpdateErrno();
result = GlobusXIOErrorSystemError("getsockname", errno);
goto error_getsockname;
}
GlobusXIOSystemDebugExitFD(socket);
return GLOBUS_SUCCESS;
error_getsockname:
GlobusXIOSystemDebugExitWithErrorFD(socket);
return result;
}
globus_result_t
globus_xio_system_socket_getpeername(
globus_xio_system_socket_t socket,
struct sockaddr * name,
globus_socklen_t * namelen)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_socket_getpeername);
GlobusXIOSystemDebugEnterFD(socket);
if(getpeername(socket, name, namelen) < 0)
{
GlobusXIOSystemUpdateErrno();
result = GlobusXIOErrorSystemError("getpeername", errno);
goto error_getpeername;
}
GlobusXIOSystemDebugExitFD(socket);
return GLOBUS_SUCCESS;
error_getpeername:
GlobusXIOSystemDebugExitWithErrorFD(socket);
return result;
}
globus_result_t
globus_xio_system_socket_bind(
globus_xio_system_socket_t socket,
struct sockaddr * addr,
globus_socklen_t addrlen)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_socket_bind);
GlobusXIOSystemDebugEnterFD(socket);
if(bind(socket, addr, addrlen) < 0)
{
GlobusXIOSystemUpdateErrno();
result = GlobusXIOErrorSystemError("bind", errno);
goto error_bind;
}
GlobusXIOSystemDebugExitFD(socket);
return GLOBUS_SUCCESS;
error_bind:
GlobusXIOSystemDebugExitWithErrorFD(socket);
return result;
}
globus_result_t
globus_xio_system_socket_listen(
globus_xio_system_socket_t socket,
int backlog)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_socket_listen);
GlobusXIOSystemDebugEnterFD(socket);
if(listen(socket, backlog) < 0)
{
GlobusXIOSystemUpdateErrno();
result = GlobusXIOErrorSystemError("listen", errno);
goto error_listen;
}
GlobusXIOSystemDebugExitFD(socket);
return GLOBUS_SUCCESS;
error_listen:
GlobusXIOSystemDebugExitWithErrorFD(socket);
return result;
}
globus_result_t
globus_xio_system_socket_connect(
globus_xio_system_socket_t socket,
const struct sockaddr * addr,
globus_socklen_t addrlen)
{
globus_result_t result;
int rc;
GlobusXIOName(globus_xio_system_socket_connect);
GlobusXIOSystemDebugEnterFD(socket);
do
{
rc = connect(socket, addr, addrlen);
GlobusXIOSystemUpdateErrno();
} while(rc < 0 && errno == EINTR);
if(rc < 0)
{
result = GlobusXIOErrorSystemError("connect", errno);
goto error_connect;
}
GlobusXIOSystemDebugExitFD(socket);
return GLOBUS_SUCCESS;
error_connect:
GlobusXIOSystemDebugExitWithErrorFD(socket);
return result;
}
globus_result_t
globus_xio_system_socket_close(
globus_xio_system_socket_t socket)
{
return globus_l_xio_system_close(socket);
}
#endif /*TARGET_ARCH_WIN32*/
globus_xio-6.6/PaxHeaders.22691/globus_xio_system_win32.c 0000644 0000000 0000000 00000000132 14243161125 021502 x ustar 00 0000000 0000000 30 mtime=1653400149.725966402
30 atime=1653401489.848559564
30 ctime=1653403998.760961418
globus_xio-6.6/globus_xio_system_win32.c 0000664 0001750 0001750 00000062544 14243161125 021655 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2014 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef _WIN32
#include "globus_i_xio_win32.h"
#include "version.h"
static
int
globus_l_xio_win32_event_activate(void);
static
int
globus_l_xio_win32_event_deactivate(void);
globus_module_descriptor_t globus_i_xio_system_module =
{
"globus_xio_system_win32",
globus_l_xio_win32_event_activate,
globus_l_xio_win32_event_deactivate,
NULL,
NULL,
&local_version
};
typedef struct globus_l_xio_win32_event_entry_s
{
/* these two are constant */
struct globus_l_xio_win32_event_thread_s * owner;
int index;
globus_i_xio_win32_event_cb_t callback;
void * user_arg;
globus_bool_t post_pending;
} globus_l_xio_win32_event_entry_t;
typedef struct globus_l_xio_win32_event_thread_s
{
win32_mutex_t lock;
win32_mutex_t post_lock;
win32_mutex_t wait_lock;
int num_entries;
globus_list_t * pending_posts;
globus_bool_t sleeping;
globus_bool_t wakeup_pending;
globus_l_xio_win32_event_entry_t * entries[MAXIMUM_WAIT_OBJECTS];
HANDLE events[MAXIMUM_WAIT_OBJECTS];
HANDLE thread_handle;
HANDLE wakeup_handle;
} globus_l_xio_win32_event_thread_t;
static win32_mutex_t globus_l_xio_win32_event_thread_lock;
static globus_l_xio_win32_event_thread_t ** globus_l_xio_win32_event_threads;
static int globus_l_xio_win32_event_thread_count;
static globus_bool_t globus_l_xio_win32_event_activated;
static
unsigned
__stdcall
globus_l_xio_win32_event_thread(
void * arg);
static
int
globus_l_xio_win32_event_activate(void)
{
WORD version;
WSADATA data;
GlobusXIOName(globus_l_xio_win32_event_activate);
if(globus_i_xio_system_common_activate() != GLOBUS_SUCCESS)
{
goto error_common;
}
GlobusXIOSystemDebugEnter();
version = MAKEWORD(2, 0);
if(WSAStartup(version, &data) != 0)
{
goto error_wsa;
}
if(globus_i_xio_win32_complete_activate() != GLOBUS_SUCCESS)
{
goto error_complete;
}
if(globus_i_xio_win32_file_activate() != GLOBUS_SUCCESS)
{
goto error_file;
}
if(globus_i_xio_win32_mode_activate() != GLOBUS_SUCCESS)
{
goto error_mode;
}
win32_mutex_init(&globus_l_xio_win32_event_thread_lock, 0);
globus_l_xio_win32_event_thread_count = 0;
globus_l_xio_win32_event_threads = 0;
globus_l_xio_win32_event_activated = GLOBUS_TRUE;
GlobusXIOSystemDebugExit();
return GLOBUS_SUCCESS;
error_mode:
globus_i_xio_win32_file_deactivate();
error_file:
globus_i_xio_win32_complete_deactivate();
error_complete:
WSACleanup();
error_wsa:
GlobusXIOSystemDebugExitWithError();
globus_i_xio_system_common_deactivate();
error_common:
return GLOBUS_FAILURE;
}
static
void
globus_l_xio_win32_event_thread_destroy(
globus_l_xio_win32_event_thread_t * thread);
static
int
globus_l_xio_win32_event_deactivate(void)
{
int i;
globus_l_xio_win32_event_thread_t * thread;
GlobusXIOName(globus_l_xio_win32_event_deactivate);
GlobusXIOSystemDebugEnter();
win32_mutex_lock(&globus_l_xio_win32_event_thread_lock);
{
globus_l_xio_win32_event_activated = GLOBUS_FALSE;
}
win32_mutex_unlock(&globus_l_xio_win32_event_thread_lock);
for(i = 0; i < globus_l_xio_win32_event_thread_count; i++)
{
thread = globus_l_xio_win32_event_threads[i];
win32_mutex_lock(&thread->lock);
{
thread->wakeup_pending = GLOBUS_TRUE;
SetEvent(thread->wakeup_handle);
}
win32_mutex_unlock(&thread->lock);
while(WaitForSingleObject(
thread->thread_handle, INFINITE) != WAIT_OBJECT_0)
{
/* XXX error */
}
globus_l_xio_win32_event_thread_destroy(thread);
}
globus_free(globus_l_xio_win32_event_threads);
win32_mutex_destroy(&globus_l_xio_win32_event_thread_lock);
globus_i_xio_win32_file_deactivate();
globus_i_xio_win32_complete_deactivate();
WSACleanup();
GlobusXIOSystemDebugExit();
globus_i_xio_system_common_deactivate();
return GLOBUS_SUCCESS;
}
static
void
globus_l_xio_win32_event_bad_apple(
const HANDLE * handles,
int count)
{
DWORD flags;
GlobusXIOName(globus_l_xio_win32_event_bad_apple);
GlobusXIOSystemDebugEnter();
while(count--)
{
globus_assert(handles[count] != 0 && "Null handle in event array");
if(!GetHandleInformation(handles[count], &flags) &&
GetLastError() == ERROR_INVALID_HANDLE)
{
/* XXX at some point we may want to forcibly remove this bad
* handle, but at the moment this api is internal and therefore
* it is indicative of an internal bug
*/
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[%s] Bad apple: handle=%lu\n",
_xio_name, (unsigned long) handles[count]));
}
}
GlobusXIOSystemDebugExit();
}
static
int
globus_l_xio_win32_event_wait(
const HANDLE * handles,
int count,
int offset,
globus_bool_t infinite)
{
int rc = -1;
DWORD wrc;
GlobusXIOName(globus_l_xio_win32_event_wait);
GlobusXIOSystemDebugEnter();
if(offset < count)
{
count -= offset;
wrc = WaitForMultipleObjects(
count, handles + offset, FALSE, infinite ? INFINITE : 0);
if(wrc == WAIT_FAILED)
{
int err = GetLastError();
GlobusXIOSystemDebugSysError("Wait error", err);
if(err == ERROR_INVALID_HANDLE)
{
globus_l_xio_win32_event_bad_apple(handles + offset, count);
}
}
else if(wrc >= WAIT_OBJECT_0 && wrc < WAIT_OBJECT_0 + count)
{
rc = wrc - WAIT_OBJECT_0 + offset;
}
else if(wrc >= WAIT_ABANDONED_0 && wrc < WAIT_ABANDONED_0 + count)
{
rc = wrc - WAIT_ABANDONED_0 + offset;
}
}
GlobusXIOSystemDebugExit();
return rc;
}
static
void
globus_l_xio_win32_event_remove(
globus_l_xio_win32_event_thread_t * thread,
globus_l_xio_win32_event_entry_t * entry);
/*
* this returns -1 or the prior index of the entry replacing this one
*/
static
int
globus_l_xio_win32_event_dispatch(
globus_l_xio_win32_event_entry_t * entry)
{
int index = -1;
GlobusXIOName(globus_l_xio_win32_event_dispatch);
GlobusXIOSystemDebugEnter();
if(!entry->callback(entry->user_arg))
{
win32_mutex_lock(&entry->owner->lock);
{
globus_l_xio_win32_event_remove(entry->owner, entry);
/* remove always takes last entry */
index = entry->owner->num_entries;
}
win32_mutex_unlock(&entry->owner->lock);
}
GlobusXIOSystemDebugExit();
return index;
}
static
unsigned
__stdcall
globus_l_xio_win32_event_thread(
void * arg)
{
globus_l_xio_win32_event_thread_t * thread;
int count;
int index;
GlobusXIOName(globus_l_xio_win32_event_thread);
GlobusXIOSystemDebugEnter();
thread = (globus_l_xio_win32_event_thread_t *) arg;
do
{
/* this lock prevents event objects from being closed while
* sleeping in the wait() call. It is only used by
* unregister_event() as a synchronization point
*/
win32_mutex_lock(&thread->wait_lock);
{
win32_mutex_lock(&thread->lock);
{
count = thread->num_entries;
thread->sleeping = GLOBUS_TRUE;
}
win32_mutex_unlock(&thread->lock);
index = globus_l_xio_win32_event_wait(
thread->events, count, 0, GLOBUS_TRUE);
}
win32_mutex_unlock(&thread->wait_lock);
win32_mutex_lock(&thread->post_lock);
{
thread->sleeping = GLOBUS_FALSE;
if(index < 0)
{
/* XXX error */
}
else if(!globus_list_empty(thread->pending_posts))
{
/*
* dispatch all pending posts
*/
globus_l_xio_win32_event_entry_t * consumed;
globus_l_xio_win32_event_entry_t * entry;
consumed = thread->entries[index];
globus_l_xio_win32_event_dispatch(consumed);
do
{
entry = (globus_l_xio_win32_event_entry_t *)
globus_list_remove(
&thread->pending_posts, thread->pending_posts);
entry->post_pending = GLOBUS_FALSE;
if(entry != consumed)
{
globus_l_xio_win32_event_dispatch(entry);
}
} while(!globus_list_empty(thread->pending_posts));
}
else
{
/*
* dispatch consumed event and check rest with 0 timeout
* The added complexity here ensures we don't starve anyone
*/
do
{
int replacement;
replacement = globus_l_xio_win32_event_dispatch(
thread->entries[index]);
if(replacement < 0 || replacement >= count)
{
/*
* either wasn't removed or the replacement is
* outside the range I am processing in this iteration
*
* skip to next entry
*/
index++;
}
else
{
/*
* replacement is in my range, reduce count and
* maintain current index.
*/
count--;
}
/* check the rest */
index = globus_l_xio_win32_event_wait(
thread->events, count, index, GLOBUS_FALSE);
} while(index >= 0);
}
}
win32_mutex_unlock(&thread->post_lock);
} while(globus_l_xio_win32_event_activated);
GlobusXIOSystemDebugExit();
return GLOBUS_SUCCESS;
}
static
globus_bool_t
globus_l_xio_win32_event_wakeup_cb(
void * arg)
{
globus_l_xio_win32_event_thread_t * thread;
GlobusXIOName(globus_l_xio_win32_event_wakeup_cb);
GlobusXIOSystemDebugEnter();
thread = (globus_l_xio_win32_event_thread_t *) arg;
win32_mutex_lock(&thread->lock);
{
thread->wakeup_pending = GLOBUS_FALSE;
}
win32_mutex_unlock(&thread->lock);
GlobusXIOSystemDebugExit();
return GLOBUS_TRUE;
}
static
globus_result_t
globus_l_xio_win32_event_add(
globus_l_xio_win32_event_entry_t ** uentry,
globus_l_xio_win32_event_thread_t * thread,
HANDLE event_handle,
globus_i_xio_win32_event_cb_t callback,
void * user_arg);
static
globus_result_t
globus_l_xio_win32_event_thread_init(
globus_l_xio_win32_event_thread_t ** uthread)
{
globus_result_t result;
globus_l_xio_win32_event_thread_t * thread;
globus_l_xio_win32_event_entry_t * entry;
GlobusXIOName(globus_l_xio_win32_event_thread_init);
GlobusXIOSystemDebugEnter();
thread = (globus_l_xio_win32_event_thread_t *)
globus_calloc(1, sizeof(globus_l_xio_win32_event_thread_t));
if(!thread)
{
result = GlobusXIOErrorMemory("thread");
goto error_alloc;
}
thread->wakeup_handle = CreateEvent(0, FALSE, FALSE, 0);
if(thread->wakeup_handle == 0)
{
result = GlobusXIOErrorSystemError(
"CreateEvent", GetLastError());
goto error_create;
}
result = globus_l_xio_win32_event_add(
&entry, thread, thread->wakeup_handle,
globus_l_xio_win32_event_wakeup_cb, thread);
if(result != GLOBUS_SUCCESS)
{
goto error_add;
}
win32_mutex_init(&thread->lock, 0);
win32_mutex_init(&thread->post_lock, 0);
win32_mutex_init(&thread->wait_lock, 0);
*uthread = thread;
GlobusXIOSystemDebugExit();
return GLOBUS_SUCCESS;
error_add:
CloseHandle(thread->wakeup_handle);
error_create:
globus_free(thread);
error_alloc:
GlobusXIOSystemDebugExitWithError();
return result;
}
static
void
globus_l_xio_win32_event_thread_destroy(
globus_l_xio_win32_event_thread_t * thread)
{
int i;
GlobusXIOName(globus_l_xio_win32_event_thread_destroy);
GlobusXIOSystemDebugEnter();
win32_mutex_destroy(&thread->wait_lock);
win32_mutex_destroy(&thread->post_lock);
win32_mutex_destroy(&thread->lock);
CloseHandle(thread->wakeup_handle);
if(thread->thread_handle)
{
CloseHandle(thread->thread_handle);
}
globus_list_free(thread->pending_posts);
for(i = 0; i < MAXIMUM_WAIT_OBJECTS; i++)
{
if(thread->entries[i])
{
globus_free(thread->entries[i]);
}
}
globus_free(thread);
GlobusXIOSystemDebugExit();
}
static
globus_result_t
globus_l_xio_win32_event_get_thread(
globus_l_xio_win32_event_thread_t ** uthread)
{
int i;
globus_l_xio_win32_event_thread_t * thread = 0;
globus_result_t result;
GlobusXIOName(globus_l_xio_win32_event_get_thread);
GlobusXIOSystemDebugEnter();
for(i = 0; i < globus_l_xio_win32_event_thread_count; i++)
{
if(globus_l_xio_win32_event_threads[i]->num_entries <
MAXIMUM_WAIT_OBJECTS)
{
thread = globus_l_xio_win32_event_threads[i];
break;
}
}
if(!thread)
{
/* make room for another MAXIMUM_WAIT_OBJECTS (64) events */
globus_l_xio_win32_event_thread_t ** new_threads;
new_threads = (globus_l_xio_win32_event_thread_t **)
globus_realloc(
globus_l_xio_win32_event_threads,
sizeof(globus_l_xio_win32_event_thread_t) *
(globus_l_xio_win32_event_thread_count + 1));
if(!new_threads)
{
result = GlobusXIOErrorMemory("new_threads");
goto error_realloc;
}
globus_l_xio_win32_event_threads = new_threads;
result = globus_l_xio_win32_event_thread_init(&thread);
if(result != GLOBUS_SUCCESS)
{
goto error_init;
}
globus_l_xio_win32_event_threads[
globus_l_xio_win32_event_thread_count] = thread;
thread->thread_handle = (HANDLE) _beginthreadex(
0, 0, globus_l_xio_win32_event_thread, thread, 0, 0);
if(thread->thread_handle == 0)
{
/* technically, i should be checking errno, but a look at the
* source code for _beginthreadex() shows LastError untouched
* after CreateThread fails
*/
result = GlobusXIOErrorSystemError(
"_beginthreadex", GetLastError());
goto error_thread;
}
globus_l_xio_win32_event_thread_count++;
}
*uthread = thread;
GlobusXIOSystemDebugExit();
return GLOBUS_SUCCESS;
error_thread:
globus_l_xio_win32_event_thread_destroy(thread);
error_init:
error_realloc:
GlobusXIOSystemDebugExitWithError();
return result;
}
/* called with thread entry locked and guaranteed room for one more entry */
static
globus_result_t
globus_l_xio_win32_event_add(
globus_l_xio_win32_event_entry_t ** uentry,
globus_l_xio_win32_event_thread_t * thread,
HANDLE event_handle,
globus_i_xio_win32_event_cb_t callback,
void * user_arg)
{
globus_result_t result;
globus_l_xio_win32_event_entry_t * entry;
GlobusXIOName(globus_l_xio_win32_event_add);
GlobusXIOSystemDebugEnter();
if(!thread->entries[thread->num_entries])
{
entry = (globus_l_xio_win32_event_entry_t *)
globus_malloc(sizeof(globus_l_xio_win32_event_entry_t));
if(!entry)
{
result = GlobusXIOErrorMemory("entry");
goto error_entry;
}
entry->owner = thread;
entry->index = thread->num_entries;
thread->entries[thread->num_entries] = entry;
}
else
{
entry = thread->entries[thread->num_entries];
}
thread->num_entries++;
entry->callback = callback;
entry->user_arg = user_arg;
entry->post_pending = GLOBUS_FALSE;
thread->events[entry->index] = event_handle;
*uentry = entry;
GlobusXIOSystemDebugExit();
return GLOBUS_SUCCESS;
error_entry:
GlobusXIOSystemDebugExitWithError();
return result;
}
/* called with thread entry locked */
static
void
globus_l_xio_win32_event_remove(
globus_l_xio_win32_event_thread_t * thread,
globus_l_xio_win32_event_entry_t * entry)
{
globus_l_xio_win32_event_entry_t * shift_entry;
GlobusXIOName(globus_l_xio_win32_event_remove);
GlobusXIOSystemDebugEnter();
thread->num_entries--;
/* if entry isn't already the last one, swap it with the last one */
if(entry->index < thread->num_entries)
{
/* swap last entry with the 'removed' one */
shift_entry = thread->entries[thread->num_entries];
shift_entry->index = entry->index;
thread->entries[shift_entry->index] = shift_entry;
/* put old entry in it's place (effectively a free store) */
entry->index = thread->num_entries;
thread->entries[entry->index] = entry;
/* move last event object to its new location */
thread->events[shift_entry->index] =
thread->events[thread->num_entries];
}
GlobusXIOSystemDebugExit();
}
globus_result_t
globus_i_xio_win32_event_register(
globus_i_xio_win32_event_entry_t * entry_handle,
HANDLE event_handle,
globus_i_xio_win32_event_cb_t callback,
void * user_arg)
{
globus_l_xio_win32_event_thread_t * thread;
globus_l_xio_win32_event_entry_t * entry;
globus_result_t result;
globus_bool_t do_wakeup = GLOBUS_FALSE;
GlobusXIOName(globus_i_xio_win32_event_register);
GlobusXIOSystemDebugEnter();
win32_mutex_lock(&globus_l_xio_win32_event_thread_lock);
if(!globus_l_xio_win32_event_activated)
{
result = GlobusXIOErrorNotActivated();
goto error_deactivated;
}
result = globus_l_xio_win32_event_get_thread(&thread);
if(result != GLOBUS_SUCCESS)
{
goto error_nothread;
}
win32_mutex_lock(&thread->lock);
{
result = globus_l_xio_win32_event_add(
&entry, thread, event_handle, callback, user_arg);
if(result != GLOBUS_SUCCESS)
{
goto error_add;
}
if(thread->sleeping && !thread->wakeup_pending)
{
thread->wakeup_pending = GLOBUS_TRUE;
do_wakeup = GLOBUS_TRUE;
}
}
win32_mutex_unlock(&thread->lock);
win32_mutex_unlock(&globus_l_xio_win32_event_thread_lock);
if(do_wakeup)
{
/*
* I do this outside the lock to avoid immediate contention in the
* thead. This leaves the possibility that the thread is gone
* before this call, resulting in segv. However, this is only
* possible if we get deactivated, which means someone's being dumb
* and using a deactivated lib.
*/
SetEvent(thread->wakeup_handle);
}
*entry_handle = entry;
GlobusXIOSystemDebugExit();
return GLOBUS_SUCCESS;
error_add:
win32_mutex_unlock(&thread->lock);
error_nothread:
error_deactivated:
win32_mutex_unlock(&globus_l_xio_win32_event_thread_lock);
GlobusXIOSystemDebugExitWithError();
return result;
}
static
globus_bool_t
globus_l_xio_win32_event_unregister_cb(
void * user_arg)
{
GlobusXIOName(globus_l_xio_win32_event_unregister_cb);
GlobusXIOSystemDebugEnter();
GlobusXIOSystemDebugExit();
return GLOBUS_FALSE;
}
/* the complexity here is to ensure that the event object will not be waited on
* when this call returns. this allows user to immediately close the event
* object
*
* this must be called with post_lock held
*/
void
globus_i_xio_win32_event_unregister(
globus_i_xio_win32_event_entry_t entry_handle)
{
globus_l_xio_win32_event_thread_t * thread;
GlobusXIOName(globus_i_xio_win32_event_unregister);
GlobusXIOSystemDebugEnter();
thread = entry_handle->owner;
entry_handle->callback = globus_l_xio_win32_event_unregister_cb;
win32_mutex_lock(&thread->lock);
{
if(thread->sleeping && !thread->wakeup_pending)
{
thread->wakeup_pending = GLOBUS_TRUE;
SetEvent(thread->wakeup_handle);
}
}
win32_mutex_unlock(&thread->lock);
win32_mutex_lock(&thread->wait_lock);
{
if(thread->sleeping)
{
/* thread is waiting on post_lock
* wait returned a signaled event, can't just remove entry
* post event to force above callback to remove entry
*/
globus_i_xio_win32_event_post(entry_handle);
}
else
{
/* thread is waiting on wait_lock, fake this event
* above callback will cause it to be removed
*/
if(entry_handle->post_pending)
{
/* remove posted event */
globus_list_remove(
&thread->pending_posts,
globus_list_search(
thread->pending_posts, entry_handle));
entry_handle->post_pending = GLOBUS_FALSE;
}
globus_l_xio_win32_event_dispatch(entry_handle);
}
}
win32_mutex_unlock(&thread->wait_lock);
GlobusXIOSystemDebugExit();
}
void
globus_i_xio_win32_event_lock(
globus_i_xio_win32_event_entry_t entry_handle)
{
GlobusXIOName(globus_i_xio_win32_event_lock);
GlobusXIOSystemDebugEnter();
win32_mutex_lock(&entry_handle->owner->post_lock);
GlobusXIOSystemDebugExit();
}
void
globus_i_xio_win32_event_unlock(
globus_i_xio_win32_event_entry_t entry_handle)
{
GlobusXIOName(globus_i_xio_win32_event_unlock);
GlobusXIOSystemDebugEnter();
win32_mutex_unlock(&entry_handle->owner->post_lock);
GlobusXIOSystemDebugExit();
}
/* this must be called with post_lock held */
void
globus_i_xio_win32_event_post(
globus_i_xio_win32_event_entry_t entry_handle)
{
globus_l_xio_win32_event_thread_t * thread;
GlobusXIOName(globus_i_xio_win32_event_post);
GlobusXIOSystemDebugEnter();
thread = entry_handle->owner;
if(!entry_handle->post_pending)
{
globus_list_insert(&thread->pending_posts, entry_handle);
entry_handle->post_pending = GLOBUS_TRUE;
win32_mutex_lock(&thread->lock);
{
if(thread->sleeping && !thread->wakeup_pending)
{
thread->wakeup_pending = GLOBUS_TRUE;
SetEvent(thread->wakeup_handle);
}
}
win32_mutex_unlock(&thread->lock);
}
GlobusXIOSystemDebugExit();
}
#endif /* _WIN32 */
globus_xio-6.6/PaxHeaders.22691/globus_i_xio_win32_complete.c 0000644 0000000 0000000 00000000132 14243161125 022276 x ustar 00 0000000 0000000 30 mtime=1653400149.721966443
30 atime=1653401490.070557368
30 ctime=1653403998.761961408
globus_xio-6.6/globus_i_xio_win32_complete.c 0000664 0001750 0001750 00000024307 14243161125 022444 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2014 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef _WIN32
#include "globus_i_xio_win32.h"
#define GlobusLWin32PollQueueInit() \
{ \
globus_l_xio_win32_poll_queue = 0; \
globus_l_xio_win32_poll_queue_tail = &globus_l_xio_win32_poll_queue; \
}
#define GlobusLWin32PollQueueEnqueue(entry) \
{ \
(entry)->next = 0; \
*globus_l_xio_win32_poll_queue_tail = (entry); \
globus_l_xio_win32_poll_queue_tail = &(entry)->next; \
}
#define GlobusLWin32PollQueueDequeue(entry) \
{ \
(entry) = globus_l_xio_win32_poll_queue; \
globus_l_xio_win32_poll_queue = (entry)->next; \
if(!globus_l_xio_win32_poll_queue) \
globus_l_xio_win32_poll_queue_tail = &globus_l_xio_win32_poll_queue;\
}
#define GlobusLWin32PollQueueEmpty() \
(globus_l_xio_win32_poll_queue == 0)
typedef struct globus_l_xio_win32_poll_entry_s
{
globus_callback_func_t callback;
void * user_arg;
struct globus_l_xio_win32_poll_entry_s * next;
} globus_l_xio_win32_poll_entry_t;
static globus_callback_handle_t globus_l_xio_win32_poll_handle;
static win32_mutex_t globus_l_xio_win32_poll_lock;
static HANDLE globus_l_xio_win32_poll_event;
static globus_bool_t globus_l_xio_win32_poll_event_sleeping;
static globus_bool_t globus_l_xio_win32_poll_event_pending;
static globus_l_xio_win32_poll_entry_t * globus_l_xio_win32_poll_queue;
static globus_l_xio_win32_poll_entry_t ** globus_l_xio_win32_poll_queue_tail;
static globus_l_xio_win32_poll_entry_t * globus_l_xio_win32_poll_free;
static
void
globus_l_xio_win32_wakeup_handler(
void * user_arg)
{
GlobusXIOName(globus_l_xio_win32_wakeup_handler);
GlobusXIOSystemDebugEnter();
if(globus_l_xio_win32_poll_event != 0)
{
SetEvent(globus_l_xio_win32_poll_event);
}
GlobusXIOSystemDebugExit();
}
static
void
globus_l_xio_win32_poll(
void * user_arg)
{
GlobusXIOName(globus_l_xio_win32_poll);
GlobusXIOSystemDebugEnter();
win32_mutex_lock(&globus_l_xio_win32_poll_lock);
{
if(GlobusLWin32PollQueueEmpty())
{
globus_reltime_t time_left;
globus_callback_get_timeout(&time_left);
if(globus_reltime_cmp(&time_left, &globus_i_reltime_zero) > 0)
{
DWORD millis = INFINITE;
if(!globus_time_reltime_is_infinity(&time_left))
{
GlobusTimeReltimeToMilliSec(millis, time_left);
}
globus_l_xio_win32_poll_event_sleeping = GLOBUS_TRUE;
win32_mutex_unlock(&globus_l_xio_win32_poll_lock);
WaitForSingleObject(globus_l_xio_win32_poll_event, millis);
win32_mutex_lock(&globus_l_xio_win32_poll_lock);
globus_l_xio_win32_poll_event_sleeping = GLOBUS_FALSE;
globus_l_xio_win32_poll_event_pending = GLOBUS_FALSE;
}
}
while(!GlobusLWin32PollQueueEmpty())
{
globus_l_xio_win32_poll_entry_t * entry;
GlobusLWin32PollQueueDequeue(entry);
win32_mutex_unlock(&globus_l_xio_win32_poll_lock);
entry->callback(entry->user_arg);
win32_mutex_lock(&globus_l_xio_win32_poll_lock);
entry->next = globus_l_xio_win32_poll_free;
globus_l_xio_win32_poll_free = entry;
if(globus_callback_has_time_expired())
{
break;
}
}
}
win32_mutex_unlock(&globus_l_xio_win32_poll_lock);
GlobusXIOSystemDebugExit();
}
int
globus_i_xio_win32_complete_activate(void)
{
globus_result_t result;
globus_reltime_t period;
GlobusXIOName(globus_i_xio_win32_complete_activate);
GlobusXIOSystemDebugEnter();
if (!globus_i_am_only_thread())
{
goto skip_activate;
}
GlobusLWin32PollQueueInit();
win32_mutex_init(&globus_l_xio_win32_poll_lock, 0);
globus_l_xio_win32_poll_event_sleeping = GLOBUS_FALSE;
globus_l_xio_win32_poll_event_pending = GLOBUS_FALSE;
globus_l_xio_win32_poll_free = 0;
globus_l_xio_win32_poll_event = CreateEvent(0, FALSE, FALSE, 0);
if(globus_l_xio_win32_poll_event == 0)
{
goto error_event;
}
GlobusTimeReltimeSet(period, 0, 0);
result = globus_callback_register_periodic(
&globus_l_xio_win32_poll_handle,
0,
&period,
globus_l_xio_win32_poll,
0);
if(result != GLOBUS_SUCCESS)
{
goto error_periodic;
}
globus_callback_add_wakeup_handler(
globus_l_xio_win32_wakeup_handler, 0);
skip_activate:
GlobusXIOSystemDebugExit();
return GLOBUS_SUCCESS;
error_periodic:
CloseHandle(globus_l_xio_win32_poll_event);
globus_l_xio_win32_poll_event = 0;
error_event:
win32_mutex_destroy(&globus_l_xio_win32_poll_lock);
GlobusXIOSystemDebugExitWithError();
return GLOBUS_FAILURE;
}
typedef struct
{
globus_cond_t cond;
globus_mutex_t mutex;
} globus_l_shutdown_info_t;
static
void
globus_l_xio_win32_unregister_poll_cb(
void * user_arg)
{
globus_l_shutdown_info_t * info;
GlobusXIOName(globus_l_xio_win32_unregister_poll_cb);
GlobusXIOSystemDebugEnter();
info = (globus_l_shutdown_info_t *) user_arg;
globus_mutex_lock(&info->mutex);
{
CloseHandle(globus_l_xio_win32_poll_event);
globus_l_xio_win32_poll_event = 0;
globus_cond_signal(&info->cond);
}
globus_mutex_unlock(&info->mutex);
GlobusXIOSystemDebugExit();
}
int
globus_i_xio_win32_complete_deactivate(void)
{
globus_result_t result;
globus_l_shutdown_info_t info;
GlobusXIOName(globus_i_xio_win32_complete_deactivate);
GlobusXIOSystemDebugEnter();
if (!globus_i_am_only_thread())
{
goto skip_deactivate;
}
globus_mutex_init(&info.mutex, NULL);
globus_cond_init(&info.cond, NULL);
globus_mutex_lock(&info.mutex);
{
result = globus_callback_unregister(
globus_l_xio_win32_poll_handle,
globus_l_xio_win32_unregister_poll_cb,
&info,
0);
if(result == GLOBUS_SUCCESS)
{
/* unregister callback destroys this event object */
while(globus_l_xio_win32_poll_event != 0)
{
globus_cond_wait(&info.cond, &info.mutex);
}
}
else
{
globus_mutex_unlock(&info.mutex);
globus_l_xio_win32_unregister_poll_cb(&info);
globus_mutex_lock(&info.mutex);
}
}
globus_mutex_unlock(&info.mutex);
globus_cond_destroy(&info.cond);
globus_mutex_destroy(&info.mutex);
win32_mutex_destroy(&globus_l_xio_win32_poll_lock);
while(globus_l_xio_win32_poll_free)
{
globus_l_xio_win32_poll_entry_t * next =
globus_l_xio_win32_poll_free->next;
globus_free(globus_l_xio_win32_poll_free);
globus_l_xio_win32_poll_free = next;
}
skip_deactivate:
GlobusXIOSystemDebugExit();
return GLOBUS_SUCCESS;
}
globus_result_t
globus_i_xio_win32_complete(
globus_callback_func_t callback,
void * user_arg)
{
globus_l_xio_win32_poll_entry_t * entry;
globus_result_t result;
GlobusXIOName(globus_i_xio_win32_complete);
GlobusXIOSystemDebugEnter();
if (! globus_i_am_only_thread())
{
return globus_callback_register_oneshot(
0,
0,
callback,
user_arg);
}
win32_mutex_lock(&globus_l_xio_win32_poll_lock);
{
if(globus_l_xio_win32_poll_free)
{
entry = globus_l_xio_win32_poll_free;
globus_l_xio_win32_poll_free = entry->next;
}
else
{
entry = (globus_l_xio_win32_poll_entry_t *)
globus_malloc(sizeof(globus_l_xio_win32_poll_entry_t));
if(!entry)
{
result = GlobusXIOErrorMemory("entry");
goto error_malloc;
}
}
entry->callback = callback;
entry->user_arg = user_arg;
GlobusLWin32PollQueueEnqueue(entry);
if(globus_l_xio_win32_poll_event_sleeping &&
!globus_l_xio_win32_poll_event_pending)
{
SetEvent(globus_l_xio_win32_poll_event);
globus_l_xio_win32_poll_event_pending = GLOBUS_TRUE;
}
}
win32_mutex_unlock(&globus_l_xio_win32_poll_lock);
GlobusXIOSystemDebugExit();
return GLOBUS_SUCCESS;
error_malloc:
return result;
}
#endif /* _WIN32 */
globus_xio-6.6/PaxHeaders.22691/globus_i_xio_win32_file.c 0000644 0000000 0000000 00000000131 14243161125 021404 x ustar 00 0000000 0000000 30 mtime=1653400149.721966443
29 atime=1653401490.28155528
30 ctime=1653403998.763961389
globus_xio-6.6/globus_i_xio_win32_file.c 0000664 0001750 0001750 00000107225 14243161125 021554 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2014 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef _WIN32
#include "globus_i_xio_win32.h"
/**
* Design notes:
*
* problem: from xio's perspective, all threads have unknown lifetime. io
* requests can not be bound to the lifetime of the requesting thread.
* if i start async io on one and the thread terminates before that io
* completes, it will be canceled by win32.
*
* solutions: in order of ease.
*
* 1)
* always block the request thread and do the operation there-- usually fast,
* sometimes network files will stall app for up to 30 seconds.
*
* 2)
* dispatch all io to separate worker thread- io can never be unexpectedly
* canceled, so it's most reliable, but always pay double context switch
* perf hit -- especially painful for small buffer (less than 512) writes
* (which should only happen in test suites or conversations, in which the
* round trip time will trump context switch time)
*
* 3)
* add a thread-hold to globus' win32 thread lib to prevent thread from
* terminating while io is pending on it, but this only protects against
* globus threads terminating (which means all of our apps will be fine) If
* win32 developers use globus libs and create their own win32 threads
* directly and terminate them before io completes, it will be canceled.
* this may be ok, since most people that would create own thread will keep
* them around until io is complete anyway. this has almost as good perf as
* blocking would in its best case and will never stall the app.
*
*
* This implementation is based on #2
* NOTE: cancellation of file i/o will not be supported at this time because
* CancelIo does not discriminate between read or write operations.
*
* Blocking io of overlapped handles is implemented by queuing asynchronous
* operations on the request thread.
* This means that user APCs may also be run.
*/
/* assume 10ms slices, try for up to 5s since the system may be thrashing */
#define LOCKED_PAGES_RETRY_COUNT 500
#define GlobusOffToOverlapped(overlapped, off) \
{ \
LARGE_INTEGER x; \
x.QuadPart = off; \
overlapped.Offset = x.LowPart; \
overlapped.OffsetHigh = x.HighPart; \
}
typedef struct
{
OVERLAPPED overlapped; /* must be first */
globus_bool_t pending;
/* io apc pending (does not track user apc) */
globus_bool_t apc_pending;
globus_xio_operation_t op;
globus_off_t offset;
globus_size_t waitforbytes;
globus_xio_iovec_t * iov;
int iovc;
struct iovec * start_iov;
int start_iovc;
globus_object_t * error;
globus_size_t nbytes;
globus_xio_system_data_callback_t callback;
void * user_arg;
/* reference to containing handle, here to avoid goofy pointer math */
struct globus_l_xio_win32_file_s * handle;
} globus_l_xio_win32_file_op_t;
typedef struct globus_l_xio_win32_file_s
{
win32_mutex_t lock;
HANDLE fd;
globus_bool_t is_overlapped;
globus_l_xio_win32_file_op_t read_op;
globus_l_xio_win32_file_op_t write_op;
} globus_l_xio_win32_file_t;
static HANDLE globus_l_xio_win32_file_thread_handle;
static globus_bool_t globus_l_xio_win32_activated;
static LARGE_INTEGER globus_l_xio_win32_file_zero_offset;
static
unsigned
__stdcall
globus_l_xio_win32_file_thread(
void * arg);
static
void
CALLBACK
globus_l_xio_win32_file_deactivate_apc(
ULONG_PTR arg);
int
globus_i_xio_win32_file_activate(void)
{
GlobusXIOName(globus_i_xio_win32_file_activate);
GlobusXIOSystemDebugEnter();
globus_l_xio_win32_file_thread_handle = (HANDLE) _beginthreadex(
0, 0, globus_l_xio_win32_file_thread, 0, 0, 0);
if(globus_l_xio_win32_file_thread_handle == 0)
{
goto error_thread;
}
globus_l_xio_win32_activated = GLOBUS_TRUE;
GlobusXIOSystemDebugExit();
return GLOBUS_SUCCESS;
error_thread:
GlobusXIOSystemDebugExitWithError();
return GLOBUS_FAILURE;
}
int
globus_i_xio_win32_file_deactivate(void)
{
GlobusXIOName(globus_i_xio_win32_file_deactivate);
GlobusXIOSystemDebugEnter();
globus_l_xio_win32_activated = GLOBUS_FALSE;
QueueUserAPC(
globus_l_xio_win32_file_deactivate_apc,
globus_l_xio_win32_file_thread_handle,
0);
while(WaitForSingleObject(
globus_l_xio_win32_file_thread_handle, INFINITE) != WAIT_OBJECT_0)
{
/* XXX error */
}
CloseHandle(globus_l_xio_win32_file_thread_handle);
GlobusXIOSystemDebugExit();
return GLOBUS_SUCCESS;
}
static
unsigned
__stdcall
globus_l_xio_win32_file_thread(
void * arg)
{
GlobusXIOName(globus_l_xio_win32_file_thread);
GlobusXIOSystemDebugEnter();
while(globus_l_xio_win32_activated)
{
SleepEx(INFINITE, GLOBUS_TRUE); /* the APCs below execute here */
}
GlobusXIOSystemDebugExit();
return GLOBUS_SUCCESS;
}
static
void
globus_l_xio_win32_file_kickout(
void * user_arg)
{
globus_l_xio_win32_file_op_t * op;
HANDLE fd;
struct iovec * start_iov;
int start_iovc;
globus_object_t * error;
globus_size_t nbytes;
globus_xio_system_data_callback_t callback;
GlobusXIOName(globus_l_xio_win32_file_kickout);
op = (globus_l_xio_win32_file_op_t *) user_arg;
fd = op->handle->fd;
GlobusXIOSystemDebugEnterFD(fd);
start_iov = op->start_iov;
start_iovc = op->start_iovc;
error = op->error;
nbytes = op->nbytes;
callback = op->callback;
user_arg = op->user_arg;
win32_mutex_lock(&op->handle->lock);
{
op->pending = GLOBUS_FALSE;
}
win32_mutex_unlock(&op->handle->lock);
callback(
error ? globus_error_put(error) : GLOBUS_SUCCESS, nbytes, user_arg);
GlobusIXIOSystemFreeIovec(start_iovc, start_iov);
GlobusXIOSystemDebugExitFD(fd);
}
static
void
CALLBACK
globus_l_xio_win32_file_deactivate_apc(
ULONG_PTR arg)
{
GlobusXIOName(globus_l_xio_win32_file_deactivate_apc);
GlobusXIOSystemDebugEnter();
/* do nothing, this just forces SleepEx to awaken */
GlobusXIOSystemDebugExit();
}
static
void
CALLBACK
globus_l_xio_win32_file_start_read_apc(
ULONG_PTR arg);
static
void
CALLBACK
globus_l_xio_win32_file_start_write_apc(
ULONG_PTR arg);
static
void
CALLBACK
globus_l_xio_win32_file_read_apc(
DWORD error,
DWORD nbytes,
LPOVERLAPPED overlapped)
{
globus_l_xio_win32_file_op_t * op;
HANDLE fd;
globus_result_t result;
GlobusXIOName(globus_l_xio_win32_file_read_apc);
op = (globus_l_xio_win32_file_op_t *) overlapped;
fd = op->handle->fd;
GlobusXIOSystemDebugEnterFD(fd);
if(op->op != 0)
{
globus_xio_operation_refresh_timeout(op->op);
}
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
("[%s] Read %ld bytes\n", _xio_name, (long)nbytes));
GlobusXIOSystemDebugRawBuffer(nbytes, op->iov->iov_base);
op->nbytes += nbytes;
op->offset += nbytes;
GlobusIXIOUtilAdjustIovec(op->iov, op->iovc, nbytes);
op->apc_pending = GLOBUS_FALSE;
if(error == ERROR_SUCCESS && op->nbytes < op->waitforbytes)
{
if(op->iovc > 0)
{
/* start next read.
* this could result in this function being reentered on error
* not a problem, though.
*/
globus_l_xio_win32_file_start_read_apc((ULONG_PTR)op);
goto reading_more;
}
else
{
op->error = GlobusXIOErrorObjParameter("waitforbytes");
}
}
else if(error == ERROR_HANDLE_EOF)
{
op->error = GlobusXIOErrorObjEOF();
}
else if(error != ERROR_SUCCESS)
{
op->error = GlobusXIOErrorObjSystemError("ReadFileEx", error);
}
if(op->op != 0)
{
result = globus_i_xio_win32_complete(
globus_l_xio_win32_file_kickout, op);
/* really cant do anything else */
if(result != GLOBUS_SUCCESS)
{
globus_panic(
GLOBUS_XIO_SYSTEM_MODULE,
result,
_XIOSL("[%s:%d] Couldn't register callback"),
_xio_name,
__LINE__);
}
}
reading_more:
GlobusXIOSystemDebugExitFD(fd);
}
static
void
CALLBACK
globus_l_xio_win32_file_write_apc(
DWORD error,
DWORD nbytes,
LPOVERLAPPED overlapped)
{
globus_l_xio_win32_file_op_t * op;
HANDLE fd;
globus_result_t result;
GlobusXIOName(globus_l_xio_win32_file_write_apc);
op = (globus_l_xio_win32_file_op_t *) overlapped;
fd = op->handle->fd;
GlobusXIOSystemDebugEnterFD(fd);
if(op->op != 0)
{
globus_xio_operation_refresh_timeout(op->op);
}
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
("[%s] Wrote %ld bytes\n", _xio_name, (long)nbytes));
GlobusXIOSystemDebugRawBuffer(nbytes, op->iov->iov_base);
op->nbytes += nbytes;
op->offset += nbytes;
GlobusIXIOUtilAdjustIovec(op->iov, op->iovc, nbytes);
op->apc_pending = GLOBUS_FALSE;
if(error == ERROR_SUCCESS && op->nbytes < op->waitforbytes)
{
if(op->iovc > 0)
{
/* start next write.
* this could result in this function being reentered on error
* not a problem, though.
*/
globus_l_xio_win32_file_start_write_apc((ULONG_PTR)op);
goto writing_more;
}
else
{
op->error = GlobusXIOErrorObjParameter("waitforbytes");
}
}
else if(error != ERROR_SUCCESS)
{
op->error = GlobusXIOErrorObjSystemError("WriteFileEx", error);
}
if(op->op != 0)
{
result = globus_i_xio_win32_complete(
globus_l_xio_win32_file_kickout, op);
/* really cant do anything else */
if(result != GLOBUS_SUCCESS)
{
globus_panic(
GLOBUS_XIO_SYSTEM_MODULE,
result,
_XIOSL("[%s:%d] Couldn't register callback"),
_xio_name,
__LINE__);
}
}
writing_more:
GlobusXIOSystemDebugExitFD(fd);
}
static
void
CALLBACK
globus_l_xio_win32_file_start_read_apc(
ULONG_PTR arg)
{
globus_l_xio_win32_file_op_t * op;
HANDLE fd;
int retry = LOCKED_PAGES_RETRY_COUNT;
int error;
GlobusXIOName(globus_l_xio_win32_file_start_read_apc);
op = (globus_l_xio_win32_file_op_t *) arg;
fd = op->handle->fd;
GlobusXIOSystemDebugEnterFD(fd);
op->apc_pending = GLOBUS_TRUE;
do
{
error = ERROR_SUCCESS;
memset(&op->overlapped, 0, sizeof(OVERLAPPED));
GlobusOffToOverlapped(op->overlapped, op->offset);
if(!ReadFileEx(fd,
op->iov->iov_base, op->iov->iov_len, &op->overlapped,
globus_l_xio_win32_file_read_apc))
{
error = GetLastError();
}
/* if the following is true, we sleep for the rest of this timeslice
* and try again. This happens when there are too many outstanding
* asynchronous operations and the os cant lock down any more pages
*/
} while((error == ERROR_INVALID_USER_BUFFER ||
error == ERROR_NOT_ENOUGH_MEMORY) && retry-- > 0 && (Sleep(0), 1));
if(retry < LOCKED_PAGES_RETRY_COUNT)
{
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[%s] fd=%lu, Retried read %d times\n",
_xio_name, (unsigned long)fd,
LOCKED_PAGES_RETRY_COUNT - (retry > 0 ? retry : 0)));
}
if(error != ERROR_SUCCESS)
{
globus_l_xio_win32_file_read_apc(error, 0, &op->overlapped);
}
GlobusXIOSystemDebugExitFD(fd);
}
static
void
CALLBACK
globus_l_xio_win32_file_start_write_apc(
ULONG_PTR arg)
{
globus_l_xio_win32_file_op_t * op;
HANDLE fd;
int retry = LOCKED_PAGES_RETRY_COUNT;
int error;
GlobusXIOName(globus_l_xio_win32_file_start_write_apc);
op = (globus_l_xio_win32_file_op_t *) arg;
fd = op->handle->fd;
GlobusXIOSystemDebugEnterFD(fd);
op->apc_pending = GLOBUS_TRUE;
do
{
error = ERROR_SUCCESS;
memset(&op->overlapped, 0, sizeof(OVERLAPPED));
GlobusOffToOverlapped(op->overlapped, op->offset);
if(!WriteFileEx(fd,
op->iov->iov_base, op->iov->iov_len, &op->overlapped,
globus_l_xio_win32_file_write_apc))
{
error = GetLastError();
}
/* if the following is true, we sleep for the rest of this timeslice
* and try again. This happens when there are too many outstanding
* asynchronous operations and the os cant lock down any more pages
*/
} while((error == ERROR_INVALID_USER_BUFFER ||
error == ERROR_NOT_ENOUGH_MEMORY) && retry-- > 0 && (Sleep(0), 1));
if(retry < LOCKED_PAGES_RETRY_COUNT)
{
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[%s] fd=%lu, Retried write %d times\n",
_xio_name, (unsigned long)fd,
LOCKED_PAGES_RETRY_COUNT - (retry > 0 ? retry : 0)));
}
if(error != ERROR_SUCCESS)
{
globus_l_xio_win32_file_write_apc(error, 0, &op->overlapped);
}
GlobusXIOSystemDebugExitFD(fd);
}
globus_result_t
globus_xio_system_file_init(
globus_xio_system_file_handle_t * uhandle,
globus_xio_system_file_t fd)
{
globus_result_t result;
globus_l_xio_win32_file_t * handle;
GlobusXIOName(globus_xio_system_file_init);
GlobusXIOSystemDebugEnterFD(fd);
handle = (globus_l_xio_win32_file_t *)
globus_calloc(1, sizeof(globus_l_xio_win32_file_t));
if(!handle)
{
result = GlobusXIOErrorMemory("handle");
goto error_alloc;
}
win32_mutex_init(&handle->lock, 0);
handle->fd = fd;
handle->read_op.handle = handle;
handle->write_op.handle = handle;
handle->is_overlapped = globus_i_xio_win32_mode_is_overlapped(fd);
if(!handle->is_overlapped)
{
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[%s] fd=%lu, Handle is NOT overlapped\n",
_xio_name, (unsigned long)fd));
}
*uhandle = handle;
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_alloc:
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
void
globus_xio_system_file_destroy(
globus_xio_system_file_handle_t handle)
{
GlobusXIOName(globus_xio_system_file_destroy);
GlobusXIOSystemDebugEnterFD(handle->fd);
win32_mutex_destroy(&handle->lock);
GlobusXIOSystemDebugExitFD(handle->fd);
globus_free(handle);
}
/* called only on non-overlapped handles */
static
void
globus_l_xio_win32_file_blocking_read(
globus_l_xio_win32_file_op_t * op)
{
DWORD nbytes;
HANDLE fd = op->handle->fd;
int error;
int rc;
GlobusXIOName(globus_l_xio_win32_file_blocking_read);
GlobusXIOSystemDebugEnterFD(fd);
do
{
if(op->nbytes < op->waitforbytes && op->iovc <= 0)
{
op->error = GlobusXIOErrorObjParameter("waitforbytes");
goto error_param;
}
memset(&op->overlapped, 0, sizeof(OVERLAPPED));
GlobusOffToOverlapped(op->overlapped, op->offset);
rc = ReadFile(fd,
op->iov->iov_base, op->iov->iov_len, &nbytes, &op->overlapped);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
("[%s] Read %ld bytes\n", _xio_name, (long)nbytes));
GlobusXIOSystemDebugRawBuffer(nbytes, op->iov->iov_base);
op->nbytes += nbytes;
op->offset += nbytes;
GlobusIXIOUtilAdjustIovec(op->iov, op->iovc, nbytes);
if(!rc || nbytes == 0)
{
error = GetLastError();
if(rc && nbytes == 0 || error == ERROR_HANDLE_EOF)
{
op->error = GlobusXIOErrorObjEOF();
}
else
{
op->error = GlobusXIOErrorObjSystemError("ReadFile", error);
}
goto error_read;
}
} while(op->nbytes < op->waitforbytes);
GlobusXIOSystemDebugExitFD(fd);
return;
error_read:
error_param:
GlobusXIOSystemDebugExitWithErrorFD(fd);
}
/* called only on non-overlapped handles */
static
void
globus_l_xio_win32_file_blocking_write(
globus_l_xio_win32_file_op_t * op)
{
DWORD nbytes;
HANDLE fd = op->handle->fd;
int rc;
GlobusXIOName(globus_l_xio_win32_file_blocking_write);
GlobusXIOSystemDebugEnterFD(fd);
do
{
if(op->nbytes < op->waitforbytes && op->iovc <= 0)
{
op->error = GlobusXIOErrorObjParameter("waitforbytes");
goto error_param;
}
memset(&op->overlapped, 0, sizeof(OVERLAPPED));
GlobusOffToOverlapped(op->overlapped, op->offset);
rc = WriteFile(fd,
op->iov->iov_base, op->iov->iov_len, &nbytes, &op->overlapped);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
("[%s] Wrote %ld bytes\n", _xio_name, (long)nbytes));
GlobusXIOSystemDebugRawBuffer(nbytes, op->iov->iov_base);
op->nbytes += nbytes;
op->offset += nbytes;
GlobusIXIOUtilAdjustIovec(op->iov, op->iovc, nbytes);
if(!rc)
{
op->error = GlobusXIOErrorObjSystemError(
"WriteFile", GetLastError());
goto error_write;
}
} while(op->nbytes < op->waitforbytes);
GlobusXIOSystemDebugExitFD(fd);
return;
error_write:
error_param:
GlobusXIOSystemDebugExitWithErrorFD(fd);
}
/* if op == null, just set up the operation... internal use only */
globus_result_t
globus_xio_system_file_register_read(
globus_xio_operation_t op,
globus_xio_system_file_handle_t handle,
globus_off_t offset,
const globus_xio_iovec_t * u_iov,
int u_iovc,
globus_size_t waitforbytes,
globus_xio_system_data_callback_t callback,
void * user_arg)
{
globus_result_t result;
HANDLE fd = handle->fd;
globus_xio_iovec_t * iov;
GlobusXIOName(globus_xio_system_file_register_read);
GlobusXIOSystemDebugEnterFD(fd);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
("[%s] Waiting for %ld bytes\n", _xio_name, (long) waitforbytes));
win32_mutex_lock(&handle->lock);
{
if(handle->read_op.pending)
{
result = GlobusXIOErrorAlreadyRegistered();
goto error_already_registered;
}
handle->read_op.pending = GLOBUS_TRUE;
}
win32_mutex_unlock(&handle->lock);
GlobusIXIOSystemAllocIovec(u_iovc, iov);
if(!iov)
{
result = GlobusXIOErrorMemory("iov");
goto error_iovec;
}
GlobusIXIOUtilTransferIovec(iov, u_iov, u_iovc);
handle->read_op.start_iov = iov;
handle->read_op.start_iovc = u_iovc;
handle->read_op.iov = iov;
handle->read_op.iovc = u_iovc;
handle->read_op.op = op;
handle->read_op.offset = offset;
handle->read_op.waitforbytes = waitforbytes;
handle->read_op.callback = callback;
handle->read_op.user_arg = user_arg;
handle->read_op.error = 0;
handle->read_op.nbytes = 0;
if(op != 0)
{
if(!handle->is_overlapped || waitforbytes == 0)
{
if(waitforbytes > 0)
{
globus_l_xio_win32_file_blocking_read(&handle->read_op);
}
/* else complete immediately, simulated select() */
result = globus_callback_register_oneshot(
0,
0,
globus_l_xio_win32_file_kickout,
&handle->read_op);
/* may have read data above, cant do anything else */
if(result != GLOBUS_SUCCESS)
{
globus_panic(
GLOBUS_XIO_SYSTEM_MODULE,
result,
_XIOSL("[%s:%d] Couldn't register callback"),
_xio_name,
__LINE__);
}
}
else
{
if(!QueueUserAPC(
globus_l_xio_win32_file_start_read_apc,
globus_l_xio_win32_file_thread_handle,
(ULONG_PTR)&handle->read_op))
{
result = GlobusXIOErrorSystemError(
"QueueUserAPC", ERROR_NOT_ENOUGH_MEMORY);
goto error_register;
}
}
}
/* handle could be destroyed by time we get here - no touch! */
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_register:
GlobusIXIOSystemFreeIovec(u_iovc, iov);
error_iovec:
win32_mutex_lock(&handle->lock);
handle->read_op.pending = GLOBUS_FALSE;
error_already_registered:
win32_mutex_unlock(&handle->lock);
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
/* if op == null, just set up the operation... internal use only */
globus_result_t
globus_xio_system_file_register_write(
globus_xio_operation_t op,
globus_xio_system_file_handle_t handle,
globus_off_t offset,
const globus_xio_iovec_t * u_iov,
int u_iovc,
globus_size_t waitforbytes,
globus_xio_system_data_callback_t callback,
void * user_arg)
{
globus_result_t result;
HANDLE fd = handle->fd;
globus_xio_iovec_t * iov;
GlobusXIOName(globus_xio_system_file_register_write);
GlobusXIOSystemDebugEnterFD(fd);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
("[%s] Waiting for %ld bytes\n", _xio_name, (long) waitforbytes));
win32_mutex_lock(&handle->lock);
{
if(handle->write_op.pending)
{
result = GlobusXIOErrorAlreadyRegistered();
goto error_already_registered;
}
handle->write_op.pending = GLOBUS_TRUE;
}
win32_mutex_unlock(&handle->lock);
GlobusIXIOSystemAllocIovec(u_iovc, iov);
if(!iov)
{
result = GlobusXIOErrorMemory("iov");
goto error_iovec;
}
GlobusIXIOUtilTransferIovec(iov, u_iov, u_iovc);
handle->write_op.start_iov = iov;
handle->write_op.start_iovc = u_iovc;
handle->write_op.iov = iov;
handle->write_op.iovc = u_iovc;
handle->write_op.op = op;
handle->write_op.offset = offset;
handle->write_op.waitforbytes = waitforbytes;
handle->write_op.callback = callback;
handle->write_op.user_arg = user_arg;
handle->write_op.error = 0;
handle->write_op.nbytes = 0;
if(op != 0)
{
if(!handle->is_overlapped || waitforbytes == 0)
{
if(waitforbytes > 0)
{
globus_l_xio_win32_file_blocking_write(&handle->write_op);
}
/* else complete immediately, simulated select() */
result = globus_callback_register_oneshot(
0,
0,
globus_l_xio_win32_file_kickout,
&handle->write_op);
/* may have read data above, cant do anything else */
if(result != GLOBUS_SUCCESS)
{
globus_panic(
GLOBUS_XIO_SYSTEM_MODULE,
result,
_XIOSL("[%s:%d] Couldn't register callback"),
_xio_name,
__LINE__);
}
}
else
{
if(!QueueUserAPC(
globus_l_xio_win32_file_start_write_apc,
globus_l_xio_win32_file_thread_handle,
(ULONG_PTR)&handle->write_op))
{
result = GlobusXIOErrorSystemError(
"QueueUserAPC", ERROR_NOT_ENOUGH_MEMORY);
goto error_register;
}
}
}
/* handle could be destroyed by time we get here - no touch! */
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_register:
GlobusIXIOSystemFreeIovec(u_iovc, iov);
error_iovec:
win32_mutex_lock(&handle->lock);
handle->write_op.pending = GLOBUS_FALSE;
error_already_registered:
win32_mutex_unlock(&handle->lock);
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
/* always blocks (even on waitforbytes == 0) */
globus_result_t
globus_xio_system_file_read(
globus_xio_system_file_handle_t handle,
globus_off_t offset,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t waitforbytes,
globus_size_t * nbytes)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_file_read);
GlobusXIOSystemDebugEnterFD(handle->fd);
/* set up read_op */
result = globus_xio_system_file_register_read(
0, handle, offset, iov, iovc, waitforbytes, 0, 0);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_xio_system_file_register_read", result);
goto error_setup;
}
if(handle->is_overlapped)
{
globus_l_xio_win32_file_start_read_apc((ULONG_PTR)&handle->read_op);
while(handle->read_op.apc_pending)
{
SleepEx(INFINITE, GLOBUS_TRUE); /* drive APCs */
}
}
else
{
globus_l_xio_win32_file_blocking_read(&handle->read_op);
}
if(handle->read_op.error)
{
result = globus_error_put(handle->read_op.error);
}
GlobusIXIOSystemFreeIovec(
handle->read_op.start_iovc, handle->read_op.start_iov);
*nbytes = handle->read_op.nbytes;
win32_mutex_lock(&handle->lock);
{
handle->read_op.pending = GLOBUS_FALSE;
}
win32_mutex_unlock(&handle->lock);
GlobusXIOSystemDebugExitFD(handle->fd);
return result;
error_setup:
*nbytes = 0;
GlobusXIOSystemDebugExitWithErrorFD(handle->fd);
return result;
}
/* always blocks (even on waitforbytes == 0) */
globus_result_t
globus_xio_system_file_write(
globus_xio_system_file_handle_t handle,
globus_off_t offset,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t waitforbytes,
globus_size_t * nbytes)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_file_write);
GlobusXIOSystemDebugEnterFD(handle->fd);
/* set up write_op */
result = globus_xio_system_file_register_write(
0, handle, offset, iov, iovc, waitforbytes, 0, 0);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_xio_system_file_register_write", result);
goto error_setup;
}
if(handle->is_overlapped)
{
globus_l_xio_win32_file_start_write_apc((ULONG_PTR)&handle->write_op);
while(handle->write_op.apc_pending)
{
SleepEx(INFINITE, GLOBUS_TRUE); /* drive APCs */
}
}
else
{
globus_l_xio_win32_file_blocking_write(&handle->write_op);
}
if(handle->write_op.error)
{
result = globus_error_put(handle->write_op.error);
}
GlobusIXIOSystemFreeIovec(
handle->write_op.start_iovc, handle->write_op.start_iov);
*nbytes = handle->write_op.nbytes;
win32_mutex_lock(&handle->lock);
{
handle->write_op.pending = GLOBUS_FALSE;
}
win32_mutex_unlock(&handle->lock);
GlobusXIOSystemDebugExitFD(handle->fd);
return result;
error_setup:
*nbytes = 0;
GlobusXIOSystemDebugExitWithErrorFD(handle->fd);
return result;
}
globus_off_t
globus_xio_system_file_get_position(
globus_xio_system_file_t fd)
{
LARGE_INTEGER offset;
GlobusXIOName(globus_xio_system_file_get_position);
GlobusXIOSystemDebugEnterFD(fd);
/* ignore errors, may be a pipe or other unseekable */
if(!SetFilePointerEx(
fd, globus_l_xio_win32_file_zero_offset, &offset, FILE_CURRENT))
{
offset = globus_l_xio_win32_file_zero_offset;
}
GlobusXIOSystemDebugExitFD(fd);
return offset.QuadPart;
}
globus_off_t
globus_xio_system_file_get_size(
globus_xio_system_file_t fd)
{
LARGE_INTEGER size;
GlobusXIOName(globus_xio_system_file_get_size);
GlobusXIOSystemDebugEnterFD(fd);
if(!GetFileSizeEx(fd, &size))
{
size.QuadPart = -1;
}
GlobusXIOSystemDebugExitFD(fd);
return size.QuadPart;
}
globus_xio_system_file_t
globus_xio_system_convert_stdio(
const char * stdio)
{
HANDLE fd = 0;
if(strcmp(stdio, "stdin") == 0)
{
fd = GetStdHandle(STD_INPUT_HANDLE);
}
else if(strcmp(stdio, "stdout") == 0)
{
fd = GetStdHandle(STD_OUTPUT_HANDLE);
}
else if(strcmp(stdio, "stderr") == 0)
{
fd = GetStdHandle(STD_ERROR_HANDLE);
}
if(fd == 0) /* GetStdHandle() can also return 0 */
{
fd = GLOBUS_XIO_SYSTEM_INVALID_FILE;
}
return fd;
}
globus_result_t
globus_xio_system_file_truncate(
globus_xio_system_file_t fd,
globus_off_t osize)
{
globus_result_t result;
LARGE_INTEGER offset;
LARGE_INTEGER size;
GlobusXIOName(globus_xio_system_file_truncate);
GlobusXIOSystemDebugEnterFD(fd);
size.QuadPart = osize;
/* save file position and move to new size */
if(!SetFilePointerEx(
fd, globus_l_xio_win32_file_zero_offset, &offset, FILE_CURRENT) ||
!SetFilePointerEx(fd, size, 0, FILE_BEGIN))
{
result = GlobusXIOErrorSystemError("SetFilePointerEx", GetLastError());
goto error_seek;
}
if(!SetEndOfFile(fd))
{
result = GlobusXIOErrorSystemError("SetEndOfFile", GetLastError());
goto error_truncate;
}
/* restore file pointer */
SetFilePointerEx(fd, offset, 0, FILE_BEGIN);
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_truncate:
SetFilePointerEx(fd, offset, 0, FILE_BEGIN);
error_seek:
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
globus_result_t
globus_xio_system_file_open(
globus_xio_system_file_t * fd,
const char * filename,
int flags,
unsigned long mode)
{
globus_result_t result;
SECURITY_ATTRIBUTES sec_attr;
DWORD access;
DWORD create_mode;
DWORD file_attr;
GlobusXIOName(globus_xio_system_file_open);
*fd = INVALID_HANDLE_VALUE;
GlobusXIOSystemDebugEnter();
access = flags & (O_RDONLY|O_WRONLY|O_RDWR);
if(access == O_WRONLY)
{
access = flags & O_APPEND
? FILE_APPEND_DATA|SYNCHRONIZE
: FILE_GENERIC_WRITE;
}
else if(access == O_RDWR)
{
access = flags & O_APPEND
? FILE_APPEND_DATA|FILE_GENERIC_READ
: FILE_GENERIC_READ|FILE_GENERIC_WRITE;
}
else
{
access = flags & O_APPEND
? FILE_APPEND_DATA|FILE_GENERIC_READ
: FILE_GENERIC_READ;
}
switch(flags & (O_CREAT|O_EXCL|O_TRUNC))
{
case O_CREAT:
create_mode = OPEN_ALWAYS;
break;
case O_CREAT|O_EXCL:
case O_CREAT|O_EXCL|O_TRUNC:
create_mode = CREATE_NEW;
break;
case O_TRUNC:
case O_TRUNC|O_EXCL: /* ignore O_EXCL on missing O_CREAT */
create_mode = TRUNCATE_EXISTING;
break;
case O_CREAT|O_TRUNC:
create_mode = CREATE_ALWAYS;
break;
default:
create_mode = OPEN_EXISTING;
break;
}
/* not supporting readonly at the moment */
file_attr = FILE_ATTRIBUTE_NORMAL;
file_attr |= FILE_FLAG_OVERLAPPED;
/* handles created by me are not inherited on exec */
sec_attr.nLength = sizeof(sec_attr);
sec_attr.lpSecurityDescriptor = 0;
sec_attr.bInheritHandle = FALSE;
*fd = CreateFile(
filename,
access,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
&sec_attr,
create_mode,
file_attr,
0);
if(*fd == INVALID_HANDLE_VALUE)
{
result = GlobusXIOErrorSystemError("CreateFile", GetLastError());
goto error_open;
}
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[%s] Opened file, %s fd=%d\n", _xio_name, filename, *fd));
GlobusXIOSystemDebugExitFD(*fd);
return GLOBUS_SUCCESS;
error_open:
GlobusXIOSystemDebugExitWithErrorFD(*fd);
return result;
}
globus_result_t
globus_xio_system_file_close(
globus_xio_system_file_t fd)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_file_close);
GlobusXIOSystemDebugEnterFD(fd);
if(!CloseHandle(fd))
{
result = GlobusXIOErrorSystemError("CloseHandle", GetLastError());
goto error_close;
}
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_close:
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
#endif /* TARGET_ARCH_WIN32 */
globus_xio-6.6/PaxHeaders.22691/globus_i_xio_win32_mode.c 0000644 0000000 0000000 00000000131 14243161125 021411 x ustar 00 0000000 0000000 30 mtime=1653400149.721966443
30 atime=1653401490.940548759
29 ctime=1653403998.76496138
globus_xio-6.6/globus_i_xio_win32_mode.c 0000664 0001750 0001750 00000005642 14243161125 021561 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2014 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef _WIN32
#include "globus_i_xio_win32.h"
/* all taken from DDK */
#ifndef NT_SUCCESS
typedef LONG NTSTATUS;
#define NT_SUCCESS(status) ((NTSTATUS)(status) >= 0)
#endif
typedef struct
{
union
{
NTSTATUS Status;
PVOID Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef enum
{
FileModeInformation = 16
} FILE_INFORMATION_CLASS;
typedef struct
{
ULONG Mode;
} FILE_MODE_INFORMATION;
typedef NTSTATUS
(__stdcall *globus_i_xio_win32_mode_nqif_t)(
HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID FileInformation,
ULONG Length,
FILE_INFORMATION_CLASS FileInformationClass);
static HMODULE globus_i_xio_win32_mode_ntdll;
static globus_i_xio_win32_mode_nqif_t globus_i_xio_win32_mode_query;
int
globus_i_xio_win32_mode_activate(void)
{
if(globus_i_xio_win32_mode_ntdll == NULL)
{
globus_i_xio_win32_mode_ntdll = LoadLibrary("ntdll.dll");
if(globus_i_xio_win32_mode_ntdll == NULL)
{
goto error_load;
}
globus_i_xio_win32_mode_query = (globus_i_xio_win32_mode_nqif_t)
GetProcAddress(
globus_i_xio_win32_mode_ntdll,
"NtQueryInformationFile");
if(globus_i_xio_win32_mode_query == NULL)
{
goto error_symbol;
}
}
return GLOBUS_SUCCESS;
error_symbol:
FreeLibrary(globus_i_xio_win32_mode_ntdll);
error_load:
return GLOBUS_FAILURE;
}
globus_bool_t
globus_i_xio_win32_mode_is_overlapped(
HANDLE handle)
{
IO_STATUS_BLOCK iosb;
FILE_MODE_INFORMATION mode;
if(NT_SUCCESS(globus_i_xio_win32_mode_query(
handle, &iosb, &mode, sizeof(mode), FileModeInformation)) &&
NT_SUCCESS(iosb.Status) &&
(mode.Mode &
(FILE_SYNCHRONOUS_IO_ALERT|FILE_SYNCHRONOUS_IO_NONALERT)) == 0)
{
return GLOBUS_TRUE;
}
else
{
return GLOBUS_FALSE;
}
}
#endif /* TARGET_ARCH_WIN32 */
globus_xio-6.6/PaxHeaders.22691/globus_i_xio_win32_socket.c 0000644 0000000 0000000 00000000132 14243161125 021756 x ustar 00 0000000 0000000 30 mtime=1653400149.721966443
30 atime=1653401490.725550887
30 ctime=1653403998.766961361
globus_xio-6.6/globus_i_xio_win32_socket.c 0000664 0001750 0001750 00000143563 14243161125 022132 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2014 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef _WIN32
#include "globus_i_xio_win32.h"
typedef struct globus_l_xio_win32_socket_s
{
win32_mutex_t lock;
SOCKET socket;
WSAEVENT event;
long eventselect;
/* ready_events is used only for select() functionality
* note, select functionality is flawed due to winsock close notification
* bug. It is possible that a read won't be signaled on a short lived
* connection. To minimize the chance of being bit by this bug,
* initialize ready_events with a read event
*/
long ready_events;
globus_i_xio_win32_event_entry_t event_entry;
globus_i_xio_system_op_info_t * read_info;
globus_i_xio_system_op_info_t * write_info;
} globus_l_xio_win32_socket_t;
static
void
globus_l_xio_win32_socket_kickout(
void * user_arg)
{
globus_i_xio_system_op_info_t * op_info;
SOCKET fd;
GlobusXIOName(globus_l_xio_win32_socket_kickout);
op_info = (globus_i_xio_system_op_info_t *) user_arg;
fd = op_info->handle->socket;
GlobusXIOSystemDebugEnterFD(fd);
if(op_info->op)
{
globus_xio_operation_disable_cancel(op_info->op);
}
switch(op_info->type)
{
case GLOBUS_I_XIO_SYSTEM_OP_CONNECT:
case GLOBUS_I_XIO_SYSTEM_OP_ACCEPT:
op_info->sop.non_data.callback(
op_info->error ? globus_error_put(op_info->error) : GLOBUS_SUCCESS,
op_info->user_arg);
break;
default:
op_info->sop.data.callback(
op_info->error ? globus_error_put(op_info->error) : GLOBUS_SUCCESS,
op_info->nbytes,
op_info->user_arg);
GlobusIXIOSystemFreeIovec(
op_info->sop.data.start_iovc,
op_info->sop.data.start_iov);
break;
}
GlobusIXIOSystemFreeOperation(op_info);
GlobusXIOSystemDebugExitFD(fd);
}
static
void
globus_l_xio_win32_socket_complete(
globus_i_xio_system_op_info_t * op_info,
globus_bool_t win32_thread)
{
SOCKET fd;
globus_result_t result;
GlobusXIOName(globus_l_xio_win32_socket_complete);
fd = op_info->handle->socket;
GlobusXIOSystemDebugEnterFD(fd);
if(!op_info->op)
{
/* internal usage */
globus_l_xio_win32_socket_kickout(op_info);
result = GLOBUS_SUCCESS;
}
else if(win32_thread)
{
result = globus_i_xio_win32_complete(
globus_l_xio_win32_socket_kickout, op_info);
}
else
{
result = globus_callback_register_oneshot(
0, 0, globus_l_xio_win32_socket_kickout, op_info);
}
/* really cant do anything else */
if(result != GLOBUS_SUCCESS)
{
globus_panic(
GLOBUS_XIO_SYSTEM_MODULE,
result,
_XIOSL("[%s:%d] Couldn't register callback"),
_xio_name,
__LINE__);
}
GlobusXIOSystemDebugExitFD(fd);
}
/* must be safe to call from win32 thread
*/
static
void
globus_l_xio_win32_socket_handle_read(
globus_l_xio_win32_socket_t * handle,
globus_i_xio_system_op_info_t * read_info)
{
globus_size_t nbytes;
globus_result_t result;
GlobusXIOName(globus_l_xio_win32_socket_handle_read);
GlobusXIOSystemDebugEnterFD(handle->socket);
result = GLOBUS_SUCCESS;
if(read_info->op)
{
globus_xio_operation_refresh_timeout(read_info->op);
}
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[%s] In globus_l_xio_win32_socket_handle_read fd=%lu, read_info->type=%d\n",
_xio_name,
(unsigned long)handle->socket, (int) read_info->type));
switch(read_info->type)
{
case GLOBUS_I_XIO_SYSTEM_OP_ACCEPT:
{
SOCKET new_fd;
new_fd = accept(handle->socket, 0, 0);
if(new_fd == INVALID_SOCKET)
{
int error = WSAGetLastError();
if(error != WSAECONNRESET && error != WSAEWOULDBLOCK)
{
char errbuf[64];
sprintf(errbuf, "accept, fd=%ld, error=%d",
(long) handle->socket, error);
result = GlobusXIOErrorSystemError(errbuf, error);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[%s] Tried to accept new connection on fd=%lu, %s\n",
_xio_name,
(unsigned long)handle->socket, errbuf));
}
else
{
char errbuf[64];
sprintf(errbuf, "accept, fd=%ld, error=%d",
(long) handle->socket, error);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[%s] Tried to accept new connection on fd=%lu, %s\n",
_xio_name,
(unsigned long)handle->socket, errbuf));
}
}
else
{
unsigned long flag = 0;
/* clear inherited attrs */
WSAEventSelect(new_fd, 0, 0);
ioctlsocket(new_fd, FIONBIO, &flag);
*read_info->sop.non_data.out_fd = new_fd;
read_info->nbytes++;
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[%s] Accepted new connection on fd=%lu, fd=%lu\n",
_xio_name,
(unsigned long)handle->socket, (unsigned long)new_fd));
}
}
break;
case GLOBUS_I_XIO_SYSTEM_OP_READ:
/* we loop repeatedly here to read all available data until
* the read would return EWOULDBLOCK. at that time, we'll get
* another event to land us back here.
* (This looping is necessary to work around a winsock bug where we
* aren't notified of the peer closing the connection on short lived
* connections)
*/
do
{
result = globus_i_xio_system_socket_try_read(
handle->socket,
read_info->sop.data.iov,
read_info->sop.data.iovc,
read_info->sop.data.flags,
read_info->sop.data.addr,
&nbytes);
if(result == GLOBUS_SUCCESS)
{
if(nbytes > 0)
{
read_info->nbytes += nbytes;
GlobusIXIOUtilAdjustIovec(
read_info->sop.data.iov,
read_info->sop.data.iovc, nbytes);
}
else if(read_info->sop.data.iovc > 0 &&
read_info->sop.data.iov[0].iov_len > 0)
{
/* we consumed read event */
handle->ready_events &= ~FD_READ;
}
}
} while(nbytes > 0 && read_info->nbytes < read_info->waitforbytes);
break;
default:
globus_assert(0 && "Unexpected type for read operation");
return;
break;
}
if(result != GLOBUS_SUCCESS)
{
read_info->error = globus_error_get(result);
}
/* always true for accept operations */
if(read_info->nbytes >= read_info->waitforbytes ||
result != GLOBUS_SUCCESS)
{
read_info->state = GLOBUS_I_XIO_SYSTEM_OP_COMPLETE;
}
GlobusXIOSystemDebugExitFD(handle->socket);
}
/* must be safe to call from win32 thread
*/
static
void
globus_l_xio_win32_socket_handle_write(
globus_l_xio_win32_socket_t * handle,
globus_i_xio_system_op_info_t * write_info)
{
globus_size_t nbytes;
globus_result_t result;
GlobusXIOName(globus_l_xio_win32_socket_handle_write);
GlobusXIOSystemDebugEnterFD(handle->socket);
result = GLOBUS_SUCCESS;
if(write_info->op)
{
globus_xio_operation_refresh_timeout(write_info->op);
}
switch(write_info->type)
{
case GLOBUS_I_XIO_SYSTEM_OP_CONNECT:
{
int err;
globus_socklen_t errlen;
errlen = sizeof(err);
if(getsockopt(
handle->socket, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen)
== SOCKET_ERROR)
{
err = WSAGetLastError();
}
if(err)
{
result = GlobusXIOErrorSystemError("connect", err);
}
}
break;
case GLOBUS_I_XIO_SYSTEM_OP_WRITE:
/* we loop repeatedly here to use up all available space until
* the write would return EWOULDBLOCK. at that time, we'll get
* another event to land us back here
*/
do
{
result = globus_i_xio_system_socket_try_write(
handle->socket,
write_info->sop.data.iov,
write_info->sop.data.iovc,
write_info->sop.data.flags,
write_info->sop.data.addr,
&nbytes);
if(result == GLOBUS_SUCCESS)
{
if(nbytes > 0)
{
write_info->nbytes += nbytes;
GlobusIXIOUtilAdjustIovec(
write_info->sop.data.iov,
write_info->sop.data.iovc, nbytes);
}
else if(write_info->sop.data.iovc > 0 &&
write_info->sop.data.iov[0].iov_len > 0)
{
/* we consumed write event */
handle->ready_events &= ~FD_WRITE;
}
}
} while(nbytes > 0 && write_info->nbytes < write_info->waitforbytes);
break;
default:
globus_assert(0 && "Unexpected type for write operation");
return;
break;
}
if(result != GLOBUS_SUCCESS)
{
write_info->error = globus_error_get(result);
}
/* always true for connect operations */
if(write_info->nbytes >= write_info->waitforbytes ||
result != GLOBUS_SUCCESS)
{
write_info->state = GLOBUS_I_XIO_SYSTEM_OP_COMPLETE;
}
GlobusXIOSystemDebugExitFD(handle->socket);
}
static
void
globus_l_xio_win32_socket_cancel_cb(
globus_xio_operation_t op,
void * user_arg,
globus_xio_error_type_t reason)
{
globus_i_xio_system_op_info_t * op_info;
GlobusXIOName(globus_l_xio_win32_socket_cancel_cb);
GlobusXIOSystemDebugEnter();
op_info = (globus_i_xio_system_op_info_t *) user_arg;
/* this access of the handle is not safe if users destroy it
* with outstanding callbacks. I don't think that is allowed, so we
* should be ok.
*/
win32_mutex_lock(&op_info->handle->lock);
{
if(op_info->state != GLOBUS_I_XIO_SYSTEM_OP_COMPLETE &&
op_info->state != GLOBUS_I_XIO_SYSTEM_OP_CANCELED)
{
op_info->error = reason == GLOBUS_XIO_ERROR_TIMEOUT
? GlobusXIOErrorObjTimeout()
: GlobusXIOErrorObjCanceled();
if(op_info->state == GLOBUS_I_XIO_SYSTEM_OP_NEW)
{
op_info->state = GLOBUS_I_XIO_SYSTEM_OP_CANCELED;
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[%s] fd=%lu, Canceling NEW\n",
_xio_name, (unsigned long)op_info->handle->socket));
}
else
{
globus_result_t result;
op_info->state = GLOBUS_I_XIO_SYSTEM_OP_COMPLETE;
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[%s] fd=%lu, Canceling Pending\n",
_xio_name, (unsigned long)op_info->handle->socket));
if(op_info->handle->read_info == op_info)
{
op_info->handle->read_info = 0;
}
else
{
globus_assert(op_info->handle->write_info == op_info);
op_info->handle->write_info = 0;
}
/* unregister and kickout now */
result = globus_callback_register_oneshot(
0,
0,
globus_l_xio_win32_socket_kickout,
op_info);
/* really cant do anything else */
if(result != GLOBUS_SUCCESS)
{
globus_panic(
GLOBUS_XIO_SYSTEM_MODULE,
result,
_XIOSL("[%s:%d] Couldn't register callback"),
_xio_name,
__LINE__);
}
}
}
}
win32_mutex_unlock(&op_info->handle->lock);
GlobusXIOSystemDebugExit();
}
/* always called from win32 thread */
static
globus_bool_t
globus_l_xio_win32_socket_event_cb(
void * user_arg)
{
globus_l_xio_win32_socket_t * handle;
WSANETWORKEVENTS wsaevents;
long events;
long clearevents = 0;
globus_i_xio_system_op_info_t * read_info = 0;
globus_i_xio_system_op_info_t * write_info = 0;
GlobusXIOName(globus_l_xio_win32_socket_event_cb);
handle = (globus_l_xio_win32_socket_t *) user_arg;
GlobusXIOSystemDebugEnterFD(handle->socket);
if(WSAEnumNetworkEvents(
handle->socket, handle->event, &wsaevents) == SOCKET_ERROR)
{
GlobusXIOSystemDebugSysError(
"WSAEnumNetworkEvents error", WSAGetLastError());
goto error_enum;
}
events = wsaevents.lNetworkEvents;
win32_mutex_lock(&handle->lock);
{
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[%s] Ready events: %s%s%s%s%s fd=%lu\n", _xio_name,
events & FD_ACCEPT ? "accept;" : "",
events & FD_CONNECT ? "connect;" : "",
events & FD_READ ? "read;" : "",
events & FD_WRITE ? "write;" : "",
events & FD_CLOSE ? "close;" : "",
(unsigned long)handle->socket));
if(events & (FD_ACCEPT|FD_READ|FD_CLOSE))
{
/* cache for select() like functionality */
handle->ready_events |= FD_READ;
if(handle->read_info)
{
globus_l_xio_win32_socket_handle_read(
handle, handle->read_info);
if(handle->read_info->state == GLOBUS_I_XIO_SYSTEM_OP_COMPLETE)
{
read_info = handle->read_info;
handle->read_info = 0;
}
}
else
{
clearevents |= FD_ACCEPT|FD_READ;
}
}
if(events & (FD_CONNECT|FD_WRITE|FD_CLOSE))
{
/* cache for select() like functionality */
handle->ready_events |= FD_WRITE;
if(handle->write_info)
{
globus_l_xio_win32_socket_handle_write(
handle, handle->write_info);
if(handle->write_info->state ==
GLOBUS_I_XIO_SYSTEM_OP_COMPLETE)
{
write_info = handle->write_info;
handle->write_info = 0;
}
}
else
{
clearevents |= FD_CONNECT|FD_WRITE;
}
}
/* clear any events we want to ignore */
if((handle->eventselect & clearevents))
{
handle->eventselect &= ~clearevents;
WSAEventSelect(handle->socket, handle->event, handle->eventselect);
}
}
win32_mutex_unlock(&handle->lock);
/* do this outside the lock to avoid unnecessary contention */
if(read_info)
{
globus_l_xio_win32_socket_complete(read_info, GLOBUS_TRUE);
}
if(write_info)
{
globus_l_xio_win32_socket_complete(write_info, GLOBUS_TRUE);
}
GlobusXIOSystemDebugExitFD(handle->socket);
return GLOBUS_TRUE;
error_enum:
GlobusXIOSystemDebugExitWithErrorFD(handle->socket);
return GLOBUS_TRUE;
}
static
globus_result_t
globus_l_xio_win32_socket_register_read(
globus_l_xio_win32_socket_t * handle,
globus_i_xio_system_op_info_t * read_info)
{
globus_result_t result;
GlobusXIOName(globus_l_xio_win32_socket_register_read);
GlobusXIOSystemDebugEnterFD(handle->socket);
/* I have to do this outside the lock because of lock inversion issues */
if(read_info->op && globus_xio_operation_enable_cancel(
read_info->op, globus_l_xio_win32_socket_cancel_cb, read_info))
{
result = GlobusXIOErrorCanceled();
goto error_cancel_enable;
}
win32_mutex_lock(&handle->lock);
{
if(read_info->state == GLOBUS_I_XIO_SYSTEM_OP_CANCELED)
{
result = globus_error_put(read_info->error);
goto error_canceled;
}
if(handle->read_info)
{
result = GlobusXIOErrorAlreadyRegistered();
goto error_already_registered;
}
read_info->state = GLOBUS_I_XIO_SYSTEM_OP_PENDING;
/* if select() functionality requested, only handle after we receive
* read event
*/
if(read_info->waitforbytes > 0 || handle->ready_events & FD_READ)
{
globus_l_xio_win32_socket_handle_read(handle, read_info);
}
if(read_info->state != GLOBUS_I_XIO_SYSTEM_OP_COMPLETE)
{
/* make sure we're set up to be notified of events */
long needevents;
if(read_info->type == GLOBUS_I_XIO_SYSTEM_OP_ACCEPT)
{
needevents = FD_ACCEPT;
}
else
{
needevents = FD_READ|FD_CLOSE;
}
if((handle->eventselect & needevents) != needevents)
{
if(WSAEventSelect(
handle->socket, handle->event,
handle->eventselect|needevents) == SOCKET_ERROR)
{
read_info->error = GlobusXIOErrorObjSystemError(
"WSAEventSelect", WSAGetLastError());
}
else
{
handle->eventselect |= needevents;
}
}
if(!read_info->error)
{
handle->read_info = read_info;
read_info = 0;
}
}
}
win32_mutex_unlock(&handle->lock);
/* do this outside the lock to avoid unnecessary contention */
if(read_info)
{
globus_l_xio_win32_socket_complete(read_info, GLOBUS_FALSE);
}
GlobusXIOSystemDebugExitFD(handle->socket);
return GLOBUS_SUCCESS;
error_already_registered:
error_canceled:
read_info->state = GLOBUS_I_XIO_SYSTEM_OP_COMPLETE;
win32_mutex_unlock(&handle->lock);
if(read_info->op)
{
globus_xio_operation_disable_cancel(read_info->op);
}
error_cancel_enable:
GlobusXIOSystemDebugExitWithErrorFD(handle->socket);
return result;
}
static
globus_result_t
globus_l_xio_win32_socket_register_write(
globus_l_xio_win32_socket_t * handle,
globus_i_xio_system_op_info_t * write_info)
{
globus_result_t result;
GlobusXIOName(globus_l_xio_win32_socket_register_write);
GlobusXIOSystemDebugEnterFD(handle->socket);
/* I have to do this outside the lock because of lock inversion issues */
if(write_info->op && globus_xio_operation_enable_cancel(
write_info->op, globus_l_xio_win32_socket_cancel_cb, write_info))
{
result = GlobusXIOErrorCanceled();
goto error_cancel_enable;
}
win32_mutex_lock(&handle->lock);
{
if(write_info->state == GLOBUS_I_XIO_SYSTEM_OP_CANCELED)
{
result = globus_error_put(write_info->error);
goto error_canceled;
}
if(handle->write_info)
{
result = GlobusXIOErrorAlreadyRegistered();
goto error_already_registered;
}
write_info->state = GLOBUS_I_XIO_SYSTEM_OP_PENDING;
/* if select() functionality requested, only handle after we receive
* write event
*
* also dont call for connect operations. waitforbytes == 0 in this
* case and handle->ready_events should not yet have a write event
*/
if(write_info->waitforbytes > 0 || handle->ready_events & FD_WRITE)
{
globus_l_xio_win32_socket_handle_write(handle, write_info);
}
if(write_info->state != GLOBUS_I_XIO_SYSTEM_OP_COMPLETE)
{
/* make sure we're set up to be notified of events */
long needevents;
if(write_info->type == GLOBUS_I_XIO_SYSTEM_OP_CONNECT)
{
needevents = FD_CONNECT|FD_CLOSE;
}
else
{
needevents = FD_WRITE|FD_CLOSE;
}
if((handle->eventselect & needevents) != needevents)
{
if(WSAEventSelect(
handle->socket, handle->event,
handle->eventselect|needevents) == SOCKET_ERROR)
{
write_info->error = GlobusXIOErrorObjSystemError(
"WSAEventSelect", WSAGetLastError());
}
else
{
handle->eventselect |= needevents;
}
}
if(!write_info->error)
{
handle->write_info = write_info;
write_info = 0;
}
}
}
win32_mutex_unlock(&handle->lock);
/* do this outside the lock to avoid unnecessary contention */
if(write_info)
{
globus_l_xio_win32_socket_complete(write_info, GLOBUS_FALSE);
}
GlobusXIOSystemDebugExitFD(handle->socket);
return GLOBUS_SUCCESS;
error_already_registered:
error_canceled:
write_info->state = GLOBUS_I_XIO_SYSTEM_OP_COMPLETE;
win32_mutex_unlock(&handle->lock);
if(write_info->op)
{
globus_xio_operation_disable_cancel(write_info->op);
}
error_cancel_enable:
GlobusXIOSystemDebugExitWithErrorFD(handle->socket);
return result;
}
globus_result_t
globus_xio_system_socket_init(
globus_xio_system_socket_handle_t * uhandle,
globus_xio_system_socket_t socket,
globus_xio_system_type_t type)
{
globus_result_t result;
globus_l_xio_win32_socket_t * handle;
unsigned long flag;
GlobusXIOName(globus_xio_system_socket_init);
GlobusXIOSystemDebugEnterFD(socket);
handle = (globus_l_xio_win32_socket_t *)
globus_calloc(1, sizeof(globus_l_xio_win32_socket_t));
if(!handle)
{
result = GlobusXIOErrorMemory("handle");
goto error_alloc;
}
handle->socket = socket;
win32_mutex_init(&handle->lock, 0);
handle->ready_events = FD_READ; /* to avoid winsock fd_close bug */
handle->event = WSACreateEvent();
if(handle->event == 0)
{
result = GlobusXIOErrorSystemError(
"WSACreateEvent", WSAGetLastError());
goto error_create;
}
flag = 1;
if(ioctlsocket(socket, FIONBIO, &flag) == SOCKET_ERROR)
{
result = GlobusXIOErrorSystemError(
"ioctlsocket", WSAGetLastError());
goto error_ioctl;
}
result = globus_i_xio_win32_event_register(
&handle->event_entry,
handle->event,
globus_l_xio_win32_socket_event_cb,
handle);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_i_xio_win32_event_register", result);
goto error_register;
}
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[%s] Registered event handle=%lu\n",
_xio_name, (unsigned long) handle->event));
*uhandle = handle;
GlobusXIOSystemDebugExitFD(socket);
return GLOBUS_SUCCESS;
error_register:
flag = 0;
ioctlsocket(socket, FIONBIO, &flag);
error_ioctl:
WSACloseEvent(handle->event);
error_create:
win32_mutex_destroy(&handle->lock);
globus_free(handle);
error_alloc:
GlobusXIOSystemDebugExitWithErrorFD(socket);
return result;
}
void
globus_xio_system_socket_destroy(
globus_xio_system_socket_handle_t handle)
{
unsigned long flag = 0;
GlobusXIOName(globus_xio_system_socket_destroy);
GlobusXIOSystemDebugEnterFD(handle->socket);
globus_assert(!handle->read_info && !handle->write_info);
/* no need to ensure entry is still registered, as I always return true
* in the callback and this is only place i unregister
*/
globus_i_xio_win32_event_lock(handle->event_entry);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_INFO,
("[%s] Unregistering event handle=%lu for socket %ld\n",
_xio_name, (unsigned long) handle->event, (long) handle->socket));
globus_i_xio_win32_event_unregister(handle->event_entry);
globus_i_xio_win32_event_unlock(handle->event_entry);
WSAEventSelect(handle->socket, 0, 0);
ioctlsocket(handle->socket, FIONBIO, &flag);
WSACloseEvent(handle->event);
win32_mutex_destroy(&handle->lock);
GlobusXIOSystemDebugExitFD(handle->socket);
globus_free(handle);
}
globus_result_t
globus_xio_system_socket_register_connect(
globus_xio_operation_t op,
globus_xio_system_socket_handle_t handle,
globus_sockaddr_t * addr,
globus_xio_system_callback_t callback,
void * user_arg)
{
globus_result_t result;
int error;
globus_i_xio_system_op_info_t * op_info;
GlobusXIOName(globus_xio_system_socket_register_connect);
GlobusXIOSystemDebugEnterFD(handle->socket);
if(connect(
handle->socket, (const struct sockaddr *) addr,
GlobusLibcSockaddrLen(addr)) == SOCKET_ERROR &&
(error = WSAGetLastError()) != WSAEWOULDBLOCK)
{
result = GlobusXIOErrorSystemError("connect", error);
goto error_connect;
}
GlobusIXIOSystemAllocOperation(op_info);
if(!op_info)
{
result = GlobusXIOErrorMemory("op_info");
goto error_op_info;
}
op_info->type = GLOBUS_I_XIO_SYSTEM_OP_CONNECT;
op_info->state = GLOBUS_I_XIO_SYSTEM_OP_NEW;
op_info->op = op;
op_info->handle = handle;
op_info->user_arg = user_arg;
op_info->sop.non_data.callback = callback;
result = globus_l_xio_win32_socket_register_write(handle, op_info);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_l_xio_win32_socket_register_write", result);
goto error_register;
}
GlobusXIOSystemDebugExitFD(handle->socket);
return GLOBUS_SUCCESS;
error_register:
GlobusIXIOSystemFreeOperation(op_info);
error_op_info:
error_connect:
GlobusXIOSystemDebugExitWithErrorFD(handle->socket);
return result;
}
globus_result_t
globus_xio_system_socket_register_accept(
globus_xio_operation_t op,
globus_xio_system_socket_handle_t listener_handle,
globus_xio_system_socket_t * out_handle,
globus_xio_system_callback_t callback,
void * user_arg)
{
globus_result_t result;
globus_i_xio_system_op_info_t * op_info;
GlobusXIOName(globus_xio_system_socket_register_accept);
GlobusXIOSystemDebugEnterFD(listener_handle->socket);
GlobusIXIOSystemAllocOperation(op_info);
if(!op_info)
{
result = GlobusXIOErrorMemory("op_info");
goto error_op_info;
}
op_info->type = GLOBUS_I_XIO_SYSTEM_OP_ACCEPT;
op_info->state = GLOBUS_I_XIO_SYSTEM_OP_NEW;
op_info->op = op;
op_info->handle = listener_handle;
op_info->user_arg = user_arg;
op_info->sop.non_data.callback = callback;
op_info->sop.non_data.out_fd = out_handle;
op_info->waitforbytes = 1;
result = globus_l_xio_win32_socket_register_read(listener_handle, op_info);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_l_xio_win32_socket_register_read", result);
goto error_register;
}
GlobusXIOSystemDebugExitFD(listener_handle->socket);
return GLOBUS_SUCCESS;
error_register:
GlobusIXIOSystemFreeOperation(op_info);
error_op_info:
GlobusXIOSystemDebugExitWithErrorFD(listener_handle->socket);
return result;
}
/* calling this with null op could cause deadlock...
* reserved for internal use
*/
/* if waitforbytes == 0 and iov[0].iov_len == 0
* behave like select()... ie notify when data ready
*/
globus_result_t
globus_l_xio_system_socket_register_read(
globus_xio_operation_t op,
globus_xio_system_socket_handle_t handle,
const globus_xio_iovec_t * u_iov,
int u_iovc,
globus_size_t waitforbytes,
globus_size_t nbytes,
int flags,
globus_sockaddr_t * out_from,
globus_xio_system_data_callback_t callback,
void * user_arg)
{
globus_result_t result;
globus_i_xio_system_op_info_t * op_info;
struct iovec * iov;
int iovc;
GlobusXIOName(globus_l_xio_system_socket_register_read);
GlobusXIOSystemDebugEnterFD(handle->socket);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
("[%s] Waiting for %ld bytes\n", _xio_name, (long) waitforbytes));
GlobusIXIOSystemAllocOperation(op_info);
if(!op_info)
{
result = GlobusXIOErrorMemory("op_info");
goto error_op_info;
}
GlobusIXIOSystemAllocIovec(u_iovc, iov);
if(!iov)
{
result = GlobusXIOErrorMemory("iov");
goto error_iovec;
}
GlobusIXIOUtilTransferIovec(iov, u_iov, u_iovc);
iovc = u_iovc;
op_info->type = GLOBUS_I_XIO_SYSTEM_OP_READ;
op_info->sop.data.start_iov = iov;
op_info->sop.data.start_iovc = iovc;
GlobusIXIOUtilAdjustIovec(iov, iovc, nbytes);
op_info->sop.data.iov = iov;
op_info->sop.data.iovc = iovc;
op_info->sop.data.addr = out_from;
op_info->sop.data.flags = flags;
op_info->state = GLOBUS_I_XIO_SYSTEM_OP_NEW;
op_info->op = op;
op_info->handle = handle;
op_info->user_arg = user_arg;
op_info->sop.data.callback = callback;
op_info->waitforbytes = waitforbytes;
op_info->nbytes = nbytes;
result = globus_l_xio_win32_socket_register_read(handle, op_info);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_l_xio_win32_socket_register_read", result);
goto error_register;
}
GlobusXIOSystemDebugExitFD(handle->socket);
return GLOBUS_SUCCESS;
error_register:
GlobusIXIOSystemFreeIovec(u_iovc, op_info->sop.data.start_iov);
error_iovec:
GlobusIXIOSystemFreeOperation(op_info);
error_op_info:
GlobusXIOSystemDebugExitWithErrorFD(handle->socket);
return result;
}
globus_result_t
globus_xio_system_socket_register_read(
globus_xio_operation_t op,
globus_xio_system_socket_handle_t handle,
const globus_xio_iovec_t * u_iov,
int u_iovc,
globus_size_t waitforbytes,
int flags,
globus_sockaddr_t * out_from,
globus_xio_system_data_callback_t callback,
void * user_arg)
{
return globus_l_xio_system_socket_register_read(
op,
handle,
u_iov,
u_iovc,
waitforbytes,
0,
flags,
out_from,
callback,
user_arg);
}
/* calling this with null op could cause deadlock...
* reserved for internal use
*/
/* if waitforbytes == 0 and iov[0].iov_len == 0
* behave like select()... ie notify when data ready
*/
globus_result_t
globus_l_xio_system_socket_register_write(
globus_xio_operation_t op,
globus_xio_system_socket_handle_t handle,
const globus_xio_iovec_t * u_iov,
int u_iovc,
globus_size_t waitforbytes,
globus_size_t nbytes,
int flags,
globus_sockaddr_t * to,
globus_xio_system_data_callback_t callback,
void * user_arg)
{
globus_result_t result;
globus_i_xio_system_op_info_t * op_info;
struct iovec * iov;
int iovc;
GlobusXIOName(globus_l_xio_system_socket_register_write);
GlobusXIOSystemDebugEnterFD(handle->socket);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
("[%s] Waiting for %ld bytes\n", _xio_name, (long) waitforbytes));
GlobusIXIOSystemAllocOperation(op_info);
if(!op_info)
{
result = GlobusXIOErrorMemory("op_info");
goto error_op_info;
}
GlobusIXIOSystemAllocIovec(u_iovc, iov);
if(!iov)
{
result = GlobusXIOErrorMemory("iov");
goto error_iovec;
}
GlobusIXIOUtilTransferIovec(iov, u_iov, u_iovc);
iovc = u_iovc;
op_info->type = GLOBUS_I_XIO_SYSTEM_OP_WRITE;
op_info->sop.data.start_iov = iov;
op_info->sop.data.start_iovc = iovc;
GlobusIXIOUtilAdjustIovec(iov, iovc, nbytes);
op_info->sop.data.iov = iov;
op_info->sop.data.iovc = iovc;
op_info->sop.data.addr = to;
op_info->sop.data.flags = flags;
op_info->state = GLOBUS_I_XIO_SYSTEM_OP_NEW;
op_info->op = op;
op_info->handle = handle;
op_info->user_arg = user_arg;
op_info->sop.data.callback = callback;
op_info->waitforbytes = waitforbytes;
op_info->nbytes = nbytes;
result = globus_l_xio_win32_socket_register_write(handle, op_info);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_l_xio_win32_socket_register_write", result);
goto error_register;
}
GlobusXIOSystemDebugExitFD(handle->socket);
return GLOBUS_SUCCESS;
error_register:
GlobusIXIOSystemFreeIovec(u_iovc, op_info->sop.data.start_iov);
error_iovec:
GlobusIXIOSystemFreeOperation(op_info);
error_op_info:
GlobusXIOSystemDebugExitWithErrorFD(handle->socket);
return result;
}
globus_result_t
globus_xio_system_socket_register_write(
globus_xio_operation_t op,
globus_xio_system_socket_handle_t handle,
const globus_xio_iovec_t * u_iov,
int u_iovc,
globus_size_t waitforbytes,
int flags,
globus_sockaddr_t * to,
globus_xio_system_data_callback_t callback,
void * user_arg)
{
return globus_l_xio_system_socket_register_write(
op,
handle,
u_iov,
u_iovc,
waitforbytes,
0,
flags,
to,
callback,
user_arg);
}
typedef struct
{
HANDLE event;
globus_size_t nbytes;
globus_object_t * error;
} globus_l_xio_win32_blocking_info_t;
static
globus_result_t
globus_l_xio_win32_blocking_init(
globus_l_xio_win32_blocking_info_t ** u_blocking_info)
{
globus_l_xio_win32_blocking_info_t * blocking_info;
globus_result_t result;
GlobusXIOName(globus_l_xio_win32_blocking_init);
GlobusXIOSystemDebugEnter();
blocking_info = (globus_l_xio_win32_blocking_info_t *)
globus_calloc(1, sizeof(globus_l_xio_win32_blocking_info_t));
if(!blocking_info)
{
result = GlobusXIOErrorMemory("blocking_info");
goto error_info;
}
blocking_info->event = CreateEvent(0, FALSE, FALSE, 0);
if(blocking_info->event == 0)
{
result = GlobusXIOErrorSystemError(
"CreateEvent", GetLastError());
goto error_create;
}
*u_blocking_info = blocking_info;
GlobusXIOSystemDebugExit();
return GLOBUS_SUCCESS;
error_create:
globus_free(blocking_info);
error_info:
*u_blocking_info = 0;
GlobusXIOSystemDebugExitWithError();
return result;
}
static
void
globus_l_xio_win32_blocking_destroy(
globus_l_xio_win32_blocking_info_t * blocking_info)
{
GlobusXIOName(globus_l_xio_win32_blocking_destroy);
GlobusXIOSystemDebugEnter();
WSACloseEvent(blocking_info->event);
globus_free(blocking_info);
GlobusXIOSystemDebugExit();
}
static
void
globus_l_xio_win32_blocking_cb(
globus_result_t result,
globus_size_t nbytes,
void * user_arg)
{
globus_l_xio_win32_blocking_info_t * blocking_info;
GlobusXIOName(globus_l_xio_win32_blocking_cb);
GlobusXIOSystemDebugEnter();
blocking_info = (globus_l_xio_win32_blocking_info_t *) user_arg;
if(result != GLOBUS_SUCCESS)
{
blocking_info->error = globus_error_get(result);
}
blocking_info->nbytes = nbytes;
SetEvent(blocking_info->event);
GlobusXIOSystemDebugExit();
}
globus_result_t
globus_xio_system_socket_read(
globus_xio_system_socket_handle_t handle,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t waitforbytes,
int flags,
globus_sockaddr_t * from,
globus_size_t * nbytes)
{
globus_result_t result;
globus_l_xio_win32_blocking_info_t * blocking_info;
GlobusXIOName(globus_xio_system_socket_read);
GlobusXIOSystemDebugEnterFD(handle->socket);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
("[%s] Waiting for %ld bytes\n", _xio_name, (long) waitforbytes));
win32_mutex_lock(&handle->lock);
{
result = globus_i_xio_system_socket_try_read(
handle->socket,
iov,
iovc,
flags,
from,
nbytes);
}
win32_mutex_unlock(&handle->lock);
if(result == GLOBUS_SUCCESS && *nbytes < waitforbytes)
{
result = globus_l_xio_win32_blocking_init(&blocking_info);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_l_xio_win32_blocking_init", result);
goto error_init;
}
result = globus_l_xio_system_socket_register_read(
0,
handle,
iov,
iovc,
waitforbytes,
*nbytes,
flags,
from,
globus_l_xio_win32_blocking_cb,
blocking_info);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_l_xio_system_socket_register_read", result);
goto error_register;
}
while(WaitForSingleObject(
blocking_info->event, INFINITE) != WAIT_OBJECT_0) {}
if(blocking_info->error)
{
result = globus_error_put(blocking_info->error);
}
*nbytes = blocking_info->nbytes;
globus_l_xio_win32_blocking_destroy(blocking_info);
}
GlobusXIOSystemDebugExitFD(handle->socket);
return result;
error_register:
globus_l_xio_win32_blocking_destroy(blocking_info);
error_init:
GlobusXIOSystemDebugExitWithErrorFD(handle->socket);
return result;
}
globus_result_t
globus_xio_system_socket_write(
globus_xio_system_socket_handle_t handle,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t waitforbytes,
int flags,
globus_sockaddr_t * to,
globus_size_t * nbytes)
{
globus_result_t result;
globus_l_xio_win32_blocking_info_t * blocking_info;
GlobusXIOName(globus_xio_system_socket_write);
GlobusXIOSystemDebugEnterFD(handle->socket);
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
("[%s] Waiting for %ld bytes\n", _xio_name, (long) waitforbytes));
win32_mutex_lock(&handle->lock);
{
result = globus_i_xio_system_socket_try_write(
handle->socket,
iov,
iovc,
flags,
to,
nbytes);
}
win32_mutex_unlock(&handle->lock);
if(result == GLOBUS_SUCCESS && *nbytes < waitforbytes)
{
result = globus_l_xio_win32_blocking_init(&blocking_info);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_l_xio_win32_blocking_init", result);
goto error_init;
}
result = globus_l_xio_system_socket_register_write(
0,
handle,
iov,
iovc,
waitforbytes,
*nbytes,
flags,
to,
globus_l_xio_win32_blocking_cb,
blocking_info);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_l_xio_system_socket_register_write", result);
goto error_register;
}
while(WaitForSingleObject(
blocking_info->event, INFINITE) != WAIT_OBJECT_0) {}
if(blocking_info->error)
{
result = globus_error_put(blocking_info->error);
}
*nbytes = blocking_info->nbytes;
globus_l_xio_win32_blocking_destroy(blocking_info);
}
GlobusXIOSystemDebugExitFD(handle->socket);
return result;
error_register:
globus_l_xio_win32_blocking_destroy(blocking_info);
error_init:
GlobusXIOSystemDebugExitWithErrorFD(handle->socket);
return result;
}
globus_result_t
globus_xio_system_socket_create(
globus_xio_system_socket_t * sock,
int domain,
int type,
int protocol)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_socket_create);
*sock = INVALID_SOCKET;
GlobusXIOSystemDebugEnter();
*sock = socket(domain, type, protocol);
if(*sock == INVALID_SOCKET)
{
result = GlobusXIOErrorSystemError("socket", WSAGetLastError());
goto error_socket;
}
/* all handles created by me are closed on exec */
SetHandleInformation((HANDLE)*sock, HANDLE_FLAG_INHERIT, 0);
GlobusXIOSystemDebugExitFD(*sock);
return GLOBUS_SUCCESS;
error_socket:
GlobusXIOSystemDebugExitWithErrorFD(*sock);
return result;
}
globus_result_t
globus_xio_system_socket_setsockopt(
globus_xio_system_socket_t socket,
int level,
int optname,
const void * optval,
socklen_t optlen)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_socket_setsockopt);
GlobusXIOSystemDebugEnterFD(socket);
if(setsockopt(socket, level, optname, optval, optlen) == SOCKET_ERROR)
{
result = GlobusXIOErrorSystemError("setsockopt", WSAGetLastError());
goto error_setsockopt;
}
GlobusXIOSystemDebugExitFD(socket);
return GLOBUS_SUCCESS;
error_setsockopt:
GlobusXIOSystemDebugExitWithErrorFD(socket);
return result;
}
globus_result_t
globus_xio_system_socket_getsockopt(
globus_xio_system_socket_t socket,
int level,
int optname,
void * optval,
socklen_t * optlen)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_socket_getsockopt);
GlobusXIOSystemDebugEnterFD(socket);
if(getsockopt(socket, level, optname, optval, optlen) == SOCKET_ERROR)
{
result = GlobusXIOErrorSystemError("getsockopt", WSAGetLastError());
goto error_getsockopt;
}
GlobusXIOSystemDebugExitFD(socket);
return GLOBUS_SUCCESS;
error_getsockopt:
GlobusXIOSystemDebugExitWithErrorFD(socket);
return result;
}
globus_result_t
globus_xio_system_socket_getsockname(
globus_xio_system_socket_t socket,
struct sockaddr * name,
socklen_t * namelen)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_socket_getsockname);
GlobusXIOSystemDebugEnterFD(socket);
if(getsockname(socket, name, namelen) == SOCKET_ERROR)
{
result = GlobusXIOErrorSystemError("getsockname", WSAGetLastError());
goto error_getsockname;
}
GlobusXIOSystemDebugExitFD(socket);
return GLOBUS_SUCCESS;
error_getsockname:
GlobusXIOSystemDebugExitWithErrorFD(socket);
return result;
}
globus_result_t
globus_xio_system_socket_getpeername(
globus_xio_system_socket_t socket,
struct sockaddr * name,
socklen_t * namelen)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_socket_getpeername);
GlobusXIOSystemDebugEnterFD(socket);
if(getpeername(socket, name, namelen) == SOCKET_ERROR)
{
result = GlobusXIOErrorSystemError("getpeername", WSAGetLastError());
goto error_getpeername;
}
GlobusXIOSystemDebugExitFD(socket);
return GLOBUS_SUCCESS;
error_getpeername:
GlobusXIOSystemDebugExitWithErrorFD(socket);
return result;
}
globus_result_t
globus_xio_system_socket_bind(
globus_xio_system_socket_t socket,
struct sockaddr * addr,
socklen_t addrlen)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_socket_bind);
GlobusXIOSystemDebugEnterFD(socket);
if(bind(socket, addr, addrlen) == SOCKET_ERROR)
{
result = GlobusXIOErrorSystemError("bind", WSAGetLastError());
goto error_bind;
}
GlobusXIOSystemDebugExitFD(socket);
return GLOBUS_SUCCESS;
error_bind:
GlobusXIOSystemDebugExitWithErrorFD(socket);
return result;
}
globus_result_t
globus_xio_system_socket_listen(
globus_xio_system_socket_t socket,
int backlog)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_socket_listen);
GlobusXIOSystemDebugEnterFD(socket);
if(listen(socket, backlog) == SOCKET_ERROR)
{
result = GlobusXIOErrorSystemError("listen", WSAGetLastError());
goto error_listen;
}
GlobusXIOSystemDebugExitFD(socket);
return GLOBUS_SUCCESS;
error_listen:
GlobusXIOSystemDebugExitWithErrorFD(socket);
return result;
}
globus_result_t
globus_xio_system_socket_connect(
globus_xio_system_socket_t socket,
const struct sockaddr * addr,
socklen_t addrlen)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_socket_connect);
GlobusXIOSystemDebugEnterFD(socket);
if(connect(socket, addr, addrlen) == SOCKET_ERROR)
{
result = GlobusXIOErrorSystemError("connect", WSAGetLastError());
goto error_connect;
}
GlobusXIOSystemDebugExitFD(socket);
return GLOBUS_SUCCESS;
error_connect:
GlobusXIOSystemDebugExitWithErrorFD(socket);
return result;
}
globus_result_t
globus_xio_system_socket_close(
globus_xio_system_socket_t socket)
{
globus_result_t result;
GlobusXIOName(globus_xio_system_socket_close);
GlobusXIOSystemDebugEnterFD(socket);
if(closesocket(socket) == SOCKET_ERROR)
{
result = GlobusXIOErrorSystemError("closesocket", WSAGetLastError());
goto error_close;
}
GlobusXIOSystemDebugExitFD(socket);
return GLOBUS_SUCCESS;
error_close:
GlobusXIOSystemDebugExitWithErrorFD(socket);
return result;
}
#endif /*TARGET_ARCH_WIN32 */
globus_xio-6.6/PaxHeaders.22691/globus_i_xio_system_common.c 0000644 0000000 0000000 00000000131 14243161125 022337 x ustar 00 0000000 0000000 30 mtime=1653400149.720966453
29 atime=1653401490.94154875
30 ctime=1653403998.767961351
globus_xio-6.6/globus_i_xio_system_common.c 0000664 0001750 0001750 00000060470 14243161125 022507 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "globus_i_xio_system_common.h"
#include
#include
#ifndef WIN32
#define GlobusLXIOSystemWouldBlock(err) \
(err == EAGAIN || err == EWOULDBLOCK)
#else
#define GlobusLXIOSystemWouldBlock(err) \
(err == EAGAIN || err == EWOULDBLOCK || err == WSAEWOULDBLOCK)
#endif
GlobusDebugDefine(GLOBUS_XIO_SYSTEM);
globus_memory_t globus_i_xio_system_op_info_memory;
globus_memory_t globus_i_xio_system_iov_memory;
static globus_bool_t globus_l_xio_system_memory_initialized;
static int globus_l_xio_iov_max;
int
globus_i_xio_system_common_activate(void)
{
GlobusXIOName(globus_i_xio_system_common_activate);
GlobusDebugInit(GLOBUS_XIO_SYSTEM, TRACE DATA INFO RAW);
GlobusXIOSystemDebugEnter();
/* I am going to leave this memory around after deactivation. To safely
* destroy them, I would need a lot more synchronization of kicked out
* callbacks
*/
if(globus_module_activate(GLOBUS_XIO_MODULE) != GLOBUS_SUCCESS)
{
goto error_activate;
}
if(!globus_l_xio_system_memory_initialized)
{
globus_l_xio_system_memory_initialized = GLOBUS_TRUE;
globus_memory_init(
&globus_i_xio_system_op_info_memory,
sizeof(globus_i_xio_system_op_info_t),
10);
globus_memory_init(
&globus_i_xio_system_iov_memory, sizeof(struct iovec) * 10, 10);
}
globus_l_xio_iov_max = -1;
#ifdef _SC_IOV_MAX
if (globus_l_xio_iov_max == -1)
{
/* If this returns -1, the limit might be indefinite if errno is
* unchanged, but that doesn't mean infinite. It's unclear what
* one is to do in that case
*/
globus_l_xio_iov_max = sysconf(_SC_IOV_MAX);
}
#endif
#ifdef IOV_MAX
if (globus_l_xio_iov_max == -1)
{
globus_l_xio_iov_max = IOV_MAX;
}
#endif
#ifdef _XOPEN_IOV_MAX
if (globus_l_xio_iov_max == -1)
{
globus_l_xio_iov_max = _XOPEN_IOV_MAX;
}
#endif
if (globus_l_xio_iov_max == -1)
{
globus_l_xio_iov_max = 16;
}
GlobusXIOSystemDebugExit();
return GLOBUS_SUCCESS;
error_activate:
GlobusXIOSystemDebugExitWithError();
GlobusDebugDestroy(GLOBUS_XIO_SYSTEM);
return GLOBUS_FAILURE;
}
int
globus_i_xio_system_common_deactivate(void)
{
GlobusXIOName(globus_i_xio_system_common_deactivate);
GlobusXIOSystemDebugEnter();
globus_module_deactivate(GLOBUS_XIO_MODULE);
GlobusXIOSystemDebugExit();
GlobusDebugDestroy(GLOBUS_XIO_SYSTEM);
return GLOBUS_SUCCESS;
}
#ifndef WIN32
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;
}
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;
}
#endif
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_recvfrom(
globus_xio_system_socket_t fd,
void * buf,
globus_size_t buflen,
int flags,
globus_sockaddr_t * from,
globus_size_t * nbytes)
{
globus_ssize_t rc = 0;
globus_result_t result;
globus_socklen_t len;
GlobusXIOName(globus_i_xio_system_try_recvfrom);
GlobusXIOSystemDebugEnterFD(fd);
if(buflen)
{
do
{
len = sizeof(globus_sockaddr_t);
rc = recvfrom(
fd,
buf,
buflen,
flags,
(struct sockaddr *) from,
&len);
GlobusXIOSystemUpdateErrno();
} while(rc < 0 && errno == EINTR);
if(rc < 0)
{
if(GlobusLXIOSystemWouldBlock(errno))
{
rc = 0;
}
else
{
result = GlobusXIOErrorSystemError("recvfrom", 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_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;
}
#ifndef WIN32
globus_result_t
globus_i_xio_system_try_write(
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_write);
GlobusXIOSystemDebugEnterFD(fd);
/* calls to this with buflen == 0 are requesting select only */
if(buflen)
{
do
{
rc = write(fd, buf, buflen);
GlobusXIOSystemUpdateErrno();
} while(rc < 0 && errno == EINTR);
if(rc < 0)
{
if(GlobusLXIOSystemWouldBlock(errno))
{
rc = 0;
}
else
{
result = GlobusXIOErrorSystemError("write", errno);
goto error_errno;
}
}
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
("[%s] Wrote %d bytes\n", _xio_name, rc));
GlobusXIOSystemDebugRawBuffer(rc, buf);
}
*nbytes = rc;
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_errno:
*nbytes = 0;
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
globus_result_t
globus_i_xio_system_try_writev(
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_writev);
GlobusXIOSystemDebugEnterFD(fd);
do
{
#ifdef HAVE_WRITEV
rc = writev(fd, iov, (iovc > globus_l_xio_iov_max)
? globus_l_xio_iov_max : iovc);
#else
rc = write(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("writev", errno);
goto error_errno;
}
}
*nbytes = rc;
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
("[%s] Wrote %d bytes\n", _xio_name, rc));
GlobusXIOSystemDebugRawIovec(rc, iov);
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_errno:
*nbytes = 0;
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
#endif
globus_result_t
globus_i_xio_system_try_send(
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_send);
GlobusXIOSystemDebugEnterFD(fd);
if(buflen)
{
do
{
rc = send(fd, buf, buflen, flags);
GlobusXIOSystemUpdateErrno();
} while(rc < 0 && errno == EINTR);
if(rc < 0)
{
if(GlobusLXIOSystemWouldBlock(errno))
{
rc = 0;
}
else
{
result = GlobusXIOErrorSystemError("send", errno);
goto error_errno;
}
}
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
("[%s] Wrote %d bytes\n", _xio_name, rc));
GlobusXIOSystemDebugRawBuffer(rc, buf);
}
*nbytes = rc;
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_errno:
*nbytes = 0;
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
globus_result_t
globus_i_xio_system_try_sendto(
globus_xio_system_socket_t fd,
void * buf,
globus_size_t buflen,
int flags,
const globus_sockaddr_t * to,
globus_size_t * nbytes)
{
globus_ssize_t rc = 0;
globus_result_t result;
GlobusXIOName(globus_i_xio_system_try_sendto);
GlobusXIOSystemDebugEnterFD(fd);
if(buflen)
{
do
{
rc = sendto(
fd,
buf,
buflen,
flags,
(struct sockaddr *) to,
GlobusLibcSockaddrLen(to));
GlobusXIOSystemUpdateErrno();
} while(rc < 0 && errno == EINTR);
if(rc < 0)
{
if(GlobusLXIOSystemWouldBlock(errno))
{
rc = 0;
}
else
{
result = GlobusXIOErrorSystemError("sendto", errno);
goto error_errno;
}
}
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
("[%s] Wrote %d bytes\n", _xio_name, rc));
GlobusXIOSystemDebugRawBuffer(rc, buf);
}
*nbytes = rc;
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_errno:
*nbytes = 0;
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
globus_result_t
globus_i_xio_system_try_sendmsg(
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_sendmsg);
GlobusXIOSystemDebugEnterFD(fd);
#ifdef WIN32
{
DWORD sent = 0;
rc = WSASendTo(
fd,
(WSABUF *) msghdr->msg_iov,
msghdr->msg_iovlen,
&sent,
flags,
msghdr->msg_name,
msghdr->msg_namelen,
0,
0);
if(rc != 0)
{
GlobusXIOSystemUpdateErrno();
rc = -1;
}
else
{
rc = sent;
}
}
#elif defined(HAVE_SENDMSG)
{
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 = sendmsg(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 = sendto(
fd,
msghdr->msg_iov[0].iov_base,
msghdr->msg_iov[0].iov_len,
flags,
(struct sockaddr *) msghdr->msg_name,
msghdr->msg_namelen);
}
else
{
rc = send(
fd,
msghdr->msg_iov[0].iov_base,
msghdr->msg_iov[0].iov_len,
flags);
}
GlobusXIOSystemUpdateErrno();
} while (rc < 0 && errno == EINTR);
}
#endif
if(rc < 0)
{
if(GlobusLXIOSystemWouldBlock(errno))
{
rc = 0;
}
else
{
result = GlobusXIOErrorSystemError("sendmsg", errno);
goto error_errno;
}
}
*nbytes = rc;
GlobusXIOSystemDebugPrintf(
GLOBUS_I_XIO_SYSTEM_DEBUG_DATA,
("[%s] Wrote %d bytes\n", _xio_name, rc));
GlobusXIOSystemDebugRawIovec(rc, msghdr->msg_iov);
GlobusXIOSystemDebugExitFD(fd);
return GLOBUS_SUCCESS;
error_errno:
*nbytes = 0;
GlobusXIOSystemDebugExitWithErrorFD(fd);
return result;
}
#ifndef WIN32
globus_result_t
globus_i_xio_system_file_try_read(
globus_xio_system_file_t handle,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t * nbytes)
{
globus_result_t result;
GlobusXIOName(globus_i_xio_system_file_try_read);
GlobusXIOSystemDebugEnter();
if(iovc == 1)
{
result = globus_i_xio_system_try_read(
handle, iov->iov_base, iov->iov_len, nbytes);
}
else
{
result = globus_i_xio_system_try_readv(handle, iov, iovc, nbytes);
}
GlobusXIOSystemDebugExit();
return result;
}
globus_result_t
globus_i_xio_system_file_try_write(
globus_xio_system_file_t handle,
const globus_xio_iovec_t * iov,
int iovc,
globus_size_t * nbytes)
{
globus_result_t result;
GlobusXIOName(globus_i_xio_system_file_try_write);
GlobusXIOSystemDebugEnter();
if(iovc == 1)
{
result = globus_i_xio_system_try_write(
handle, iov->iov_base, iov->iov_len, nbytes);
}
else
{
result = globus_i_xio_system_try_writev(handle, iov, iovc, nbytes);
}
GlobusXIOSystemDebugExit();
return result;
}
#endif
globus_result_t
globus_i_xio_system_socket_try_read(
globus_xio_system_socket_t handle,
const globus_xio_iovec_t * iov,
int iovc,
int flags,
globus_sockaddr_t * from,
globus_size_t * nbytes)
{
globus_result_t result;
GlobusXIOName(globus_i_xio_system_socket_try_read);
GlobusXIOSystemDebugEnter();
#if !defined(WIN32)
/* posix can use readv for sockets */
if(!flags && !from && iovc > 1)
{
result = globus_i_xio_system_try_readv(handle, iov, iovc, nbytes);
}
else
#endif
if(iovc == 1)
{
if(from)
{
result = globus_i_xio_system_try_recvfrom(
handle, iov->iov_base, iov->iov_len, flags, from, nbytes);
}
else
{
result = globus_i_xio_system_try_recv(
handle, iov->iov_base, iov->iov_len, flags, nbytes);
}
}
else
{
struct msghdr msghdr;
memset(&msghdr, 0, sizeof(msghdr));
msghdr.msg_iov = (struct iovec *) iov;
msghdr.msg_iovlen = iovc;
if(from)
{
msghdr.msg_name = from;
msghdr.msg_namelen = sizeof(globus_sockaddr_t);
}
result = globus_i_xio_system_try_recvmsg(
handle, &msghdr, flags, nbytes);
}
GlobusXIOSystemDebugExit();
return result;
}
globus_result_t
globus_i_xio_system_socket_try_write(
globus_xio_system_socket_t handle,
const globus_xio_iovec_t * iov,
int iovc,
int flags,
globus_sockaddr_t * to,
globus_size_t * nbytes)
{
globus_result_t result;
GlobusXIOName(globus_i_xio_system_socket_try_write);
GlobusXIOSystemDebugEnter();
#if !defined(WIN32)
/* posix can use writev for sockets */
if(!flags && !to && iovc > 1)
{
result = globus_i_xio_system_try_writev(handle, iov, iovc, nbytes);
}
else
#endif
if(iovc == 1)
{
if(to)
{
result = globus_i_xio_system_try_sendto(
handle, iov->iov_base, iov->iov_len, flags, to, nbytes);
}
else
{
result = globus_i_xio_system_try_send(
handle, iov->iov_base, iov->iov_len, flags, nbytes);
}
}
else
{
struct msghdr msghdr;
memset(&msghdr, 0, sizeof(msghdr));
msghdr.msg_iov = (struct iovec *) iov;
msghdr.msg_iovlen = iovc;
if(to)
{
msghdr.msg_name = (struct sockaddr *) to;
msghdr.msg_namelen = GlobusLibcSockaddrLen(to);
}
result = globus_i_xio_system_try_sendmsg(
handle, &msghdr, flags, nbytes);
}
GlobusXIOSystemDebugExit();
return result;
}
globus_xio-6.6/PaxHeaders.22691/globus_xio_load.c 0000644 0000000 0000000 00000000132 14243161125 020053 x ustar 00 0000000 0000000 30 mtime=1653400149.723966423
30 atime=1653401491.184546345
30 ctime=1653403998.769961332
globus_xio-6.6/globus_xio_load.c 0000664 0001750 0001750 00000013300 14243161125 020210 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "globus_xio_load.h"
#include "globus_i_xio.h"
/* provides local_extensions */
#include "extensions.h"
globus_extension_registry_t globus_i_xio_driver_registry;
int
globus_i_xio_load_init(void)
{
GlobusXIOName(globus_i_xio_load_init);
GlobusXIODebugInternalEnter();
globus_extension_register_builtins(local_extensions);
GlobusXIODebugInternalExit();
return GLOBUS_SUCCESS;
}
int
globus_i_xio_load_destroy(void)
{
GlobusXIOName(globus_i_xio_load_destroy);
GlobusXIODebugInternalEnter();
globus_extension_unregister_builtins(local_extensions);
GlobusXIODebugInternalExit();
return GLOBUS_SUCCESS;
}
globus_result_t
globus_xio_driver_load(
const char * driver_name,
globus_xio_driver_t * out_driver)
{
char buf[256];
globus_extension_handle_t handle;
globus_bool_t activated = GLOBUS_FALSE;
globus_result_t result;
int rc;
globus_xio_driver_hook_t * hook;
GlobusXIOName(globus_xio_driver_load);
GlobusXIODebugEnter();
if(!driver_name)
{
result = GlobusXIOErrorParameter("driver_name");
goto error_param;
}
if(!out_driver)
{
result = GlobusXIOErrorParameter("out_driver");
goto error_param;
}
hook = (globus_xio_driver_hook_t *) globus_extension_lookup(
&handle, GLOBUS_XIO_DRIVER_REGISTRY, (void *) driver_name);
if(!hook)
{
snprintf(buf, 256, GLOBUS_XIO_EXTENSION_FORMAT, driver_name);
buf[255] = 0;
rc = globus_extension_activate(buf);
if(rc != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
_XIOSL("driver activation"), (globus_result_t) rc);
goto error_activate;
}
activated = GLOBUS_TRUE;
hook = (globus_xio_driver_hook_t *) globus_extension_lookup(
&handle, GLOBUS_XIO_DRIVER_REGISTRY, (void *) driver_name);
}
if(!hook)
{
result = GlobusXIOErrorInvalidDriver(_XIOSL("driver lookup failed"));
goto error_hook;
}
result = hook->init(out_driver);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(_XIOSL("globus_xio_driver_init_t"), result);
goto error_init;
}
globus_assert(
*out_driver && "init returned success but passed back null driver");
(*out_driver)->hook = hook;
(*out_driver)->extension_handle = handle;
(*out_driver)->extension_activated = activated;
return GLOBUS_SUCCESS;
error_init:
globus_extension_release(handle);
error_hook:
if(activated)
{
globus_extension_deactivate(buf);
}
error_activate:
*out_driver = GLOBUS_NULL;
error_param:
GlobusXIODebugExitWithError();
return result;
}
globus_result_t
globus_xio_driver_unload(
globus_xio_driver_t driver)
{
globus_xio_driver_hook_t * hook;
globus_extension_handle_t handle;
globus_bool_t activated;
globus_result_t result;
char buf[256];
GlobusXIOName(globus_xio_driver_unload);
GlobusXIODebugEnter();
if(!driver)
{
result = GlobusXIOErrorParameter("driver");
goto error_param;
}
hook = driver->hook;
handle = driver->extension_handle;
activated = driver->extension_activated;
if(activated)
{
snprintf(buf, 256, GLOBUS_XIO_EXTENSION_FORMAT, driver->name);
buf[255] = 0;
}
globus_i_xio_close_handles(driver);
hook->destroy(driver);
globus_extension_release(handle);
if(activated)
{
globus_extension_deactivate(buf);
}
GlobusXIODebugExit();
return GLOBUS_SUCCESS;
error_param:
GlobusXIODebugExitWithError();
return result;
}
globus_bool_t
globus_xio_driver_error_match(
globus_xio_driver_t driver,
globus_object_t * error,
int type)
{
globus_bool_t match = GLOBUS_FALSE;
GlobusXIOName(globus_xio_driver_error_match);
GlobusXIODebugEnter();
if(driver && driver->extension_handle)
{
match = globus_extension_error_match(
driver->extension_handle, error, type);
}
GlobusXIODebugExit();
return match;
}
globus_bool_t
globus_xio_driver_error_match_with_cb(
globus_xio_driver_t driver,
globus_object_t * error,
globus_extension_error_match_cb_t callback,
void * type)
{
globus_bool_t match = GLOBUS_FALSE;
GlobusXIOName(globus_xio_driver_error_match);
GlobusXIODebugEnter();
if(driver && driver->extension_handle)
{
match = globus_extension_error_match_with_cb(
driver->extension_handle, error, callback, type);
}
GlobusXIODebugExit();
return match;
}
globus_xio-6.6/PaxHeaders.22691/globus-vararg-enums-doxygen-filter.pl 0000644 0000000 0000000 00000000132 14243161125 023731 x ustar 00 0000000 0000000 30 mtime=1653400149.720966453
30 atime=1653401492.071537569
30 ctime=1653403998.770961322
globus_xio-6.6/globus-vararg-enums-doxygen-filter.pl 0000775 0001750 0001750 00000022047 14243161125 024101 0 ustar 00johndoe johndoe 0000000 0000000 #!/usr/bin/perl
#
# Copyright 1999-2006 University of Chicago
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# this script expects source file as an arg
# types are defined with
# GlobusVarArgDefine(name, rettype, function, ... /* fixed params */)
# the enum will be the first param after the fixed params followed by
# any params defined in the GlobusVarArgEnum block
# enums can be preceded with 2 comment blocks, the first starting with
# GlobusVarArgEnum() The second is the vararg
# parameter list
use strict;
# these two are used as 'static' variables for following function
my $line = '';
my $comment = '';
# function returns either whole comment or everything between comments
sub get_next_blob()
{
my $blob = '';
if(!$line && !defined($line = ))
{
return '';
}
while($line)
{
if($comment)
{
# still looking for the end of the comment
if($line =~ m/\*\//)
{
my $comment_end = $line;
# extract the comment portion
$comment_end =~ s/(.*?\*\/).*\n?/$1/;
$comment_end = $comment . $comment_end;
$comment = '';
# keep remainder of line
$line =~ s/.*?\*\/(.*)/$1/;
return $comment_end;
}
$comment .= $line;
}
elsif($line =~ m/\/\*/)
{
# got a beginning of a comment
my $prefix = $line;
# keep the comment portion
$line =~ s/.*?\/\*(.*)/$1/;
# save the preceding portion
$prefix =~ s/(.*?)\/\*.*\n?/$1/;
$blob .= $prefix;
# make sure this isn't a /* embedded in a string
# this does not catch multi-line strings (which are deprecated in C)
# this is hacky perl which counts the number of matches in a string
my $count = () = $prefix =~ m/(?;
}
# only get here on eof
if(!$blob)
{
$blob = $comment;
}
return $blob;
}
sub strip_comments($)
{
my $str = shift;
return join("", split(/(?:^\s*(?:\/\*+|\*+(?!\/)))|(?:\*+\/)/m, $str));
}
sub normalize_params($)
{
my $str = shift;
$str =~ s/^\s*(.*?)\s*$/$1/s; # trim whitespace from ends
$str =~ s/\s+/ /sg; # collaspe all whitespace into single space
$str =~ s/\s*,\s*/, /sg; # make all ',' have only one space on right
return $str;
}
############################################################################
my $source_file = shift(@ARGV) || die("Error: Missing argument!");
my %types;
my $functions = '';
open(SOURCE, $source_file)
|| die("Error: could not open $source_file");
while((my $blob = get_next_blob()))
{
if($blob =~ m/^\/\*/)
{
my $stripped = strip_comments($blob);
my @matches = ($stripped =~ m/GlobusVarArgDefine\(\s*(.*?)\s*\)/sg);
if(@matches)
{
# strip from blob
$blob =~ s/GlobusVarArgDefine\(.*?\)//sg;
foreach my $match (@matches)
{
my @params = split(/\s*,\s*/s, $match);
if(@params >= 3)
{
my $type = shift(@params);
my $rettype = shift(@params);
my $func_name = shift(@params);
$types{$type} = {
'rettype' => $rettype,
'name' => $func_name,
'begin_prototype' =>
'(' . normalize_params(join(',', @params)) };
}
else
{
print(STDERR
"Warning: GlobusVarArgDefine has too few args\n");
}
}
}
elsif($stripped =~ s/^.*GlobusVarArgEnum\((.*?)\).*$/$1/s)
{
# stripped types that we need to output for
my @types = split(/\s*,\s*/s, $stripped);
my $docblock;
my $end_prototype = ')';
# strip GlobusVarArgEnum from blob
$blob =~ s/GlobusVarArgEnum\(.*?\)/\@overload/s;
# normalize leading whitespace before * in comment block so
# that doxygen doesn't think its a blockquote
$blob =~ s/^ *\*/ */mg;
$docblock = $blob . "\n";
# next blob is either an optional prototype comment or the enum
$blob = get_next_blob();
# we might get all whitespace first
if($blob =~ m/^\s+$/s)
{
$blob = get_next_blob();
}
if($blob =~ m/^\/\*/)
{
# we've got the var arg parameters now
$blob = strip_comments($blob);
if(!($blob =~ m/^\s*$/s))
{
$end_prototype =
', ' . normalize_params($blob) . $end_prototype;
}
$blob = get_next_blob();
}
while($blob =~ m/^((\/\*)|(\s*$))/)
{
# any additional comments or whitespace we just spew out
print($blob);
$blob = get_next_blob();
}
# blob now has to be enum or bust
my $enum = $blob;
if($enum =~ s/^\s*(\w+).*$/$1/s)
{
my $comment = ' /** See usage for: ';
my $found = 0;
# create function sigs
foreach my $type (@types)
{
if(defined($types{$type}))
{
my $function = $types{$type}{'name'} .
$types{$type}{'begin_prototype'} . ', ' .
$enum . $end_prototype;
$functions .= $docblock .
$types{$type}{'rettype'} . " $function;\n";
if($found)
{
$comment .= ', ';
}
$comment .= "\@link $function " .
$types{$type}{'name'} . ' @endlink';
$found = 1;
}
else
{
print(STDERR
"Warning: undefined type '$type' in GlobusVarArgEnum\n");
}
}
$comment .= " */\n";
if($found)
{
$blob = $comment . $blob;
if(0)
{
# add comment with references to usage
if($blob =~ m/[^,}]*,/)
{
$blob =~ s/^(\s*\w+\s*(=[^,]+)?,)/$1$comment/s;
}
else
{
# last enum in the block
$blob =~
s/^(\s*\w+(\s*=[^}]+?(?=\n\s*(}|$)))?)/$1$comment/s;
}
}
}
else
{
print($docblock);
}
}
else
{
# not enum, warn and spew docblock
print(STDERR
"Warning: missing enum value after GlobusVarArgEnum block\n");
print($docblock);
}
}
}
print($blob);
}
print($functions);
exit(0);
globus_xio-6.6/PaxHeaders.22691/globus_i_xio_win32.h 0000644 0000000 0000000 00000000132 14243161125 020413 x ustar 00 0000000 0000000 30 mtime=1653400149.720966453
30 atime=1653401497.410484743
30 ctime=1653403998.772961303
globus_xio-6.6/globus_i_xio_win32.h 0000664 0001750 0001750 00000012545 14243161125 020562 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2014 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GLOBUS_I_XIO_WIN32_H_
#define GLOBUS_I_XIO_WIN32_H_
#include "globus_i_xio_system_common.h"
#include
#include
#include
typedef struct globus_l_xio_win32_event_entry_s *
globus_i_xio_win32_event_entry_t;
/**
* this callback is called from within threads managed by this lib.
*
* you must synchronize access between this and globus interface calls
* and you must not call into globus calls unless globus has been built
* threaded.
*
* this callback is called while holding the
* globus_i_xio_win32_event_lock()
*
* return false to unregister event handle, true to keep it
*
* (this callback will not be reentered for any given event object)
*/
typedef
globus_bool_t
(*globus_i_xio_win32_event_cb_t)(
void * user_arg);
globus_result_t
globus_i_xio_win32_event_register(
globus_i_xio_win32_event_entry_t * entry_handle,
HANDLE event_handle,
globus_i_xio_win32_event_cb_t callback,
void * user_arg);
/**
* must be called after globus_i_xio_win32_event_lock()
* Do NOT call within globus_i_xio_win32_event_cb_t callback
*/
void
globus_i_xio_win32_event_unregister(
globus_i_xio_win32_event_entry_t entry_handle);
/**
* this lock effectively prevents events from occurring on the specified
* handle (and others, but not all) while it is held. This lock is also
* held while calling event callbacks (so, don't call it within callbacks)
*/
void
globus_i_xio_win32_event_lock(
globus_i_xio_win32_event_entry_t entry_handle);
void
globus_i_xio_win32_event_unlock(
globus_i_xio_win32_event_entry_t entry_handle);
/**
* must be called after globus_i_xio_win32_event_lock()
* Do NOT call within globus_i_xio_win32_event_cb_t callback
*/
void
globus_i_xio_win32_event_post(
globus_i_xio_win32_event_entry_t entry_handle);
int
globus_i_xio_win32_complete_activate(void);
int
globus_i_xio_win32_complete_deactivate(void);
int
globus_i_xio_win32_file_activate(void);
int
globus_i_xio_win32_file_deactivate(void);
/**
* dispatch callback to globus threads
*/
globus_result_t
globus_i_xio_win32_complete(
globus_callback_func_t callback,
void * user_arg);
int
globus_i_xio_win32_mode_activate(void);
globus_bool_t
globus_i_xio_win32_mode_is_overlapped(
HANDLE handle);
typedef CRITICAL_SECTION win32_mutex_t;
#define win32_mutex_init(x, y) InitializeCriticalSection(x)
#define win32_mutex_destroy(x) DeleteCriticalSection(x)
#define win32_mutex_lock(x) EnterCriticalSection(x)
#define win32_mutex_unlock(x) LeaveCriticalSection(x)
#define GlobusXIOSystemDebugSysError(message, err) \
do \
{ \
if(GlobusDebugTrue( \
GLOBUS_XIO_SYSTEM, GLOBUS_I_XIO_SYSTEM_DEBUG_INFO)) \
{ \
char * msg = NULL; \
int err_ = err; \
\
FormatMessage( \
FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, \
NULL, \
err_, \
0, \
(LPTSTR)&msg, \
0, \
NULL); \
\
GlobusDebugMyPrintf( \
GLOBUS_XIO_SYSTEM, \
("[%s] %s: %d:%s", _xio_name, message, err_, msg)); \
\
if(msg) \
{ \
LocalFree(msg); \
} \
} \
} while(0)
#endif
globus_xio-6.6/PaxHeaders.22691/GLOBUS_LICENSE 0000644 0000000 0000000 00000000131 14243161125 016615 x ustar 00 0000000 0000000 30 mtime=1653400149.712966534
29 atime=1653401889.26858143
30 ctime=1653403998.774961284
globus_xio-6.6/GLOBUS_LICENSE 0000664 0001750 0001750 00000023676 14243161125 016774 0 ustar 00johndoe johndoe 0000000 0000000
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
globus_xio-6.6/PaxHeaders.22691/builtins 0000644 0000000 0000000 00000000132 14243170537 016321 x ustar 00 0000000 0000000 30 mtime=1653403999.167957536
30 atime=1653403999.531954065
30 ctime=1653403999.167957536
globus_xio-6.6/builtins/ 0000775 0001750 0001750 00000000000 14243170537 016536 5 ustar 00johndoe johndoe 0000000 0000000 globus_xio-6.6/builtins/PaxHeaders.22691/Makefile.in 0000644 0000000 0000000 00000000131 14243161507 020437 x ustar 00 0000000 0000000 29 mtime=1653400391.85451294
30 atime=1653401060.925803527
30 ctime=1653403998.816960884
globus_xio-6.6/builtins/Makefile.in 0000664 0001750 0001750 00000044607 14243161507 020613 0 ustar 00johndoe johndoe 0000000 0000000 # Makefile.in generated by automake 1.13.4 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = builtins
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/dirt.sh $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/globus_i_xio_config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
ctags-recursive dvi-recursive html-recursive info-recursive \
install-data-recursive install-dvi-recursive \
install-exec-recursive install-html-recursive \
install-info-recursive install-pdf-recursive \
install-ps-recursive install-recursive installcheck-recursive \
installdirs-recursive pdf-recursive ps-recursive \
tags-recursive uninstall-recursive
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
am__recursive_targets = \
$(RECURSIVE_TARGETS) \
$(RECURSIVE_CLEAN_TARGETS) \
$(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
distdir
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = $(SUBDIRS)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
sed_rest='s,^[^/]*/*,,'; \
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
sed_butlast='s,/*[^/]*$$,,'; \
while test -n "$$dir1"; do \
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
if test "$$first" != "."; then \
if test "$$first" = ".."; then \
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
else \
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
if test "$$first2" = "$$first"; then \
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
else \
dir2="../$$dir2"; \
fi; \
dir0="$$dir0"/"$$first"; \
fi; \
fi; \
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
done; \
reldir="$$dir2"
ACLOCAL = @ACLOCAL@
AGE_VERSION = @AGE_VERSION@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AS = @AS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BUILTIN_EXTENSIONS_DEC = @BUILTIN_EXTENSIONS_DEC@
BUILTIN_EXTENSIONS_DEF = @BUILTIN_EXTENSIONS_DEF@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DIRT_BRANCH_ID = @DIRT_BRANCH_ID@
DIRT_TIMESTAMP = @DIRT_TIMESTAMP@
DLLTOOL = @DLLTOOL@
DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GLOBUS_COMMON_CFLAGS = @GLOBUS_COMMON_CFLAGS@
GLOBUS_COMMON_LIBS = @GLOBUS_COMMON_LIBS@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAJOR_VERSION = @MAJOR_VERSION@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MINOR_VERSION = @MINOR_VERSION@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_DEPS = @PACKAGE_DEPS@
PACKAGE_DEP_CFLAGS = @PACKAGE_DEP_CFLAGS@
PACKAGE_DEP_LIBS = @PACKAGE_DEP_LIBS@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
XIO_BUILTIN_DIRS = @XIO_BUILTIN_DIRS@
XIO_BUILTIN_LIBS = @XIO_BUILTIN_LIBS@
XIO_BUILTIN_PC_INCLUDES = @XIO_BUILTIN_PC_INCLUDES@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
SUBDIRS = $(XIO_BUILTIN_DIRS)
all: all-recursive
.SUFFIXES:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign builtins/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign builtins/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
# This directory's subdirectories are mostly independent; you can cd
# into them and run 'make' without going through this Makefile.
# To change the values of 'make' variables: instead of editing Makefiles,
# (1) if the variable is set in 'config.status', edit 'config.status'
# (which will cause the Makefiles to be regenerated when you run 'make');
# (2) otherwise, pass the desired values on the 'make' command line.
$(am__recursive_targets):
@fail=; \
if $(am__make_keepgoing); then \
failcom='fail=yes'; \
else \
failcom='exit 1'; \
fi; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-recursive
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-recursive
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-recursive
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
$(am__make_dryrun) \
|| test -d "$(distdir)/$$subdir" \
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|| exit 1; \
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
$(am__relativize); \
new_distdir=$$reldir; \
dir1=$$subdir; dir2="$(top_distdir)"; \
$(am__relativize); \
new_top_distdir=$$reldir; \
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
($(am__cd) $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$$new_top_distdir" \
distdir="$$new_distdir" \
am__remove_distdir=: \
am__skip_length_check=: \
am__skip_mode_fix=: \
distdir) \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-recursive
all-am: Makefile
installdirs: installdirs-recursive
installdirs-am:
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-recursive
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags
dvi: dvi-recursive
dvi-am:
html: html-recursive
html-am:
info: info-recursive
info-am:
install-data-am:
install-dvi: install-dvi-recursive
install-dvi-am:
install-exec-am:
install-html: install-html-recursive
install-html-am:
install-info: install-info-recursive
install-info-am:
install-man:
install-pdf: install-pdf-recursive
install-pdf-am:
install-ps: install-ps-recursive
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am:
.MAKE: $(am__recursive_targets) install-am install-strip
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
check-am clean clean-generic clean-libtool cscopelist-am ctags \
ctags-am distclean distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
installdirs-am maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
ps ps-am tags tags-am uninstall uninstall-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
globus_xio-6.6/builtins/PaxHeaders.22691/Makefile.am 0000644 0000000 0000000 00000000132 14243161125 020423 x ustar 00 0000000 0000000 30 mtime=1653400149.713966524
30 atime=1653400391.827513213
30 ctime=1653403998.818960865
globus_xio-6.6/builtins/Makefile.am 0000664 0001750 0001750 00000000036 14243161125 020562 0 ustar 00johndoe johndoe 0000000 0000000 SUBDIRS = $(XIO_BUILTIN_DIRS)
globus_xio-6.6/builtins/PaxHeaders.22691/file 0000644 0000000 0000000 00000000132 14243170536 017237 x ustar 00 0000000 0000000 30 mtime=1653403998.865960416
30 atime=1653403999.531954065
30 ctime=1653403998.865960416
globus_xio-6.6/builtins/file/ 0000775 0001750 0001750 00000000000 14243170536 017454 5 ustar 00johndoe johndoe 0000000 0000000 globus_xio-6.6/builtins/file/PaxHeaders.22691/Makefile.in 0000644 0000000 0000000 00000000132 14243161507 021357 x ustar 00 0000000 0000000 30 mtime=1653400391.901512464
30 atime=1653401061.041802379
30 ctime=1653403998.860960464
globus_xio-6.6/builtins/file/Makefile.in 0000664 0001750 0001750 00000050675 14243161507 021534 0 ustar 00johndoe johndoe 0000000 0000000 # Makefile.in generated by automake 1.13.4 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = builtins/file
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/build-aux/depcomp $(include_HEADERS)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/dirt.sh $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/globus_i_xio_config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libglobus_xio_file_driver_la_LIBADD =
am_libglobus_xio_file_driver_la_OBJECTS = globus_xio_file_driver.lo
libglobus_xio_file_driver_la_OBJECTS = \
$(am_libglobus_xio_file_driver_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
libglobus_xio_file_driver_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
$(AM_CFLAGS) $(CFLAGS) $(libglobus_xio_file_driver_la_LDFLAGS) \
$(LDFLAGS) -o $@
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(libglobus_xio_file_driver_la_SOURCES)
DIST_SOURCES = $(libglobus_xio_file_driver_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
test -z "$$files" \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
am__installdirs = "$(DESTDIR)$(includedir)"
HEADERS = $(include_HEADERS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AGE_VERSION = @AGE_VERSION@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AS = @AS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BUILTIN_EXTENSIONS_DEC = @BUILTIN_EXTENSIONS_DEC@
BUILTIN_EXTENSIONS_DEF = @BUILTIN_EXTENSIONS_DEF@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DIRT_BRANCH_ID = @DIRT_BRANCH_ID@
DIRT_TIMESTAMP = @DIRT_TIMESTAMP@
DLLTOOL = @DLLTOOL@
DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GLOBUS_COMMON_CFLAGS = @GLOBUS_COMMON_CFLAGS@
GLOBUS_COMMON_LIBS = @GLOBUS_COMMON_LIBS@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAJOR_VERSION = @MAJOR_VERSION@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MINOR_VERSION = @MINOR_VERSION@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_DEPS = @PACKAGE_DEPS@
PACKAGE_DEP_CFLAGS = @PACKAGE_DEP_CFLAGS@
PACKAGE_DEP_LIBS = @PACKAGE_DEP_LIBS@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
XIO_BUILTIN_DIRS = @XIO_BUILTIN_DIRS@
XIO_BUILTIN_LIBS = @XIO_BUILTIN_LIBS@
XIO_BUILTIN_PC_INCLUDES = @XIO_BUILTIN_PC_INCLUDES@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
include_HEADERS = globus_xio_file_driver.h
noinst_LTLIBRARIES = libglobus_xio_file_driver.la
AM_CPPFLAGS = -I$(top_srcdir) -DGLOBUS_BUILTIN=1 $(PACKAGE_DEP_CFLAGS)
libglobus_xio_file_driver_la_SOURCES = globus_xio_file_driver.c
libglobus_xio_file_driver_la_LDFLAGS = $(PACKAGE_DEP_LIBS)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign builtins/file/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign builtins/file/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
test -z "$$locs" || { \
echo rm -f $${locs}; \
rm -f $${locs}; \
}
libglobus_xio_file_driver.la: $(libglobus_xio_file_driver_la_OBJECTS) $(libglobus_xio_file_driver_la_DEPENDENCIES) $(EXTRA_libglobus_xio_file_driver_la_DEPENDENCIES)
$(AM_V_CCLD)$(libglobus_xio_file_driver_la_LINK) $(libglobus_xio_file_driver_la_OBJECTS) $(libglobus_xio_file_driver_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globus_xio_file_driver.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
install-includeHEADERS: $(include_HEADERS)
@$(NORMAL_INSTALL)
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
$(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
$(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
done
uninstall-includeHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES) $(HEADERS)
installdirs:
for dir in "$(DESTDIR)$(includedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am: install-includeHEADERS
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-includeHEADERS
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
ctags-am distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am \
install-includeHEADERS install-info install-info-am \
install-man install-pdf install-pdf-am install-ps \
install-ps-am install-strip installcheck installcheck-am \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
uninstall-am uninstall-includeHEADERS
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
globus_xio-6.6/builtins/file/PaxHeaders.22691/Makefile.am 0000644 0000000 0000000 00000000132 14243161125 021342 x ustar 00 0000000 0000000 30 mtime=1653400149.713966524
30 atime=1653400391.863512849
30 ctime=1653403998.862960445
globus_xio-6.6/builtins/file/Makefile.am 0000664 0001750 0001750 00000000443 14243161125 021503 0 ustar 00johndoe johndoe 0000000 0000000
include_HEADERS = globus_xio_file_driver.h
noinst_LTLIBRARIES = libglobus_xio_file_driver.la
AM_CPPFLAGS = -I$(top_srcdir) -DGLOBUS_BUILTIN=1 $(PACKAGE_DEP_CFLAGS)
libglobus_xio_file_driver_la_SOURCES = globus_xio_file_driver.c
libglobus_xio_file_driver_la_LDFLAGS = $(PACKAGE_DEP_LIBS)
globus_xio-6.6/builtins/file/PaxHeaders.22691/globus_xio_file_driver.h 0000644 0000000 0000000 00000000132 14243161125 024203 x ustar 00 0000000 0000000 30 mtime=1653400149.713966524
30 atime=1653401470.566750347
30 ctime=1653403998.863960436
globus_xio-6.6/builtins/file/globus_xio_file_driver.h 0000664 0001750 0001750 00000032177 14243161125 024355 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GLOBUS_XIO_FILE_DRIVER_H
#define GLOBUS_XIO_FILE_DRIVER_H
/**
* @file globus_xio_file_driver.h
* @brief XIO File Driver
*/
#include "globus_xio_system.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup globus_xio_file_driver Globus XIO File Driver
* @ingroup globus_xio
* @brief Globus XIO File Driver
*
* File I/O driver
*/
/**
* @defgroup globus_xio_file_driver_instance Opening/Closing
* @ingroup globus_xio_file_driver
* @brief Opening/Closing
*
* An XIO handle with the file driver can be created with
* @ref globus_xio_handle_create()
*
* If there is no handle set on the attr passed to the
* @ref globus_xio_open() call, it performs the equivalent of an
* open() call. In this case, the contact string must contain
* either a pathname or one of stdin://, stdout://, or stderr://. If a
* pathname is used, that path is opened. If one of the schemes are used
* the corresponding stdio handle is used (retrieved with fileno()).
*
* In either of the above cases, it is most efficient to call the blocking
* version of globus_xio_open(). It is also safe to call within a locked
* critical section.
*
* When the XIO handle is closed, the file driver will destroy its internal
* resources and close the fd (unless this fd was set on an attr or converted
* from one of the stdio handles).
*/
/**
* @defgroup globus_xio_file_driver_io Reading/Writing
* @ingroup globus_xio_file_driver
* @brief Reading/Writing
*
* Both the @ref globus_xio_register_read() and
* @ref globus_xio_register_write() calls follow similar semantics as described
* below.
*
* If the waitforbytes parameter is greater than zero, the io will happen
* asynchronously and be completed when at least waitforbytes has been
* read/written.
*
* If the waitforbytes parameter is equal to zero, one of the following
* alternative behaviors occur:
*
* If the length of the buffer is > 0 the read or write happens synchronously.
* If the user is using one of the blocking xio calls, no internal callback
* will occur.
*
* If the length of the buffer is also 0, the call behaves like an asynchronous
* notification of data ready to be either read or written. ie, an
* asynchronous select().
*
* In any case, when an error or EOF occurs before the waitforbytes request
* has been met, the outgoing nbytes is set to the amount of data actually
* read/written before the error or EOF occurred.
*
* You may either use GLOBUS_XIO_FILE_SEEK or GLOBUS_XIO_SEEK to position the
* file pointer before each read or write or you can specify the
* desired offset on a data descriptor with the xio cmd,
* GLOBUS_XIO_DD_SET_OFFSET. Simultaneous reading and writing is only
* predictable if the data descriptor method is used.
*/
/**
* @defgroup globus_xio_file_driver_envs Environment Variables
* @ingroup globus_xio_file_driver
* @brief Environment Variables
*
* The file driver uses the following environment variables
* - GLOBUS_XIO_FILE_DEBUG Available if using a debug build. See globus_debug.h
* for format. The File driver defines the levels TRACE for all function
* call tracing and INFO for write buffer sizes
* - GLOBUS_XIO_SYSTEM_DEBUG Available if using a debug build.
* See globus_debug.h for format. The File driver uses globus_xio_system
* (along with the TCP and UDP drivers) which defines the following
* levels: TRACE for all function call tracing, DATA for data read and
* written counts, INFO for some special events, and RAW which dumps the
* raw buffers actually read or written. This can contain binary data,
* so be careful when you enable it.
*/
/**
* @defgroup globus_xio_file_driver_cntls Attributes and Cntls
* @ingroup globus_xio_file_driver
* @brief Attributes and Cntls
*
* File driver specific attrs and cntls.
*
* @see globus_xio_attr_cntl()
* @see globus_xio_handle_cntl()
*/
/**
* @defgroup globus_xio_file_driver_types Types
* @ingroup globus_xio_file_driver
* @brief Types
*/
/**
* @defgroup globus_xio_file_driver_errors Error Types
* @ingroup globus_xio_file_driver
* @brief Error Types
*
* The File driver is very close to the system code, so most errors
* reported by it are converted from the system errno. A few of the exceptions
* are GLOBUS_XIO_ERROR_EOF, GLOBUS_XIO_ERROR_COMMAND,
* GLOBUS_XIO_ERROR_CONTACT_STRING, and GLOBUS_XIO_ERROR_CANCELED
*
* @see globus_error_errno_match()
*/
/**
* Invalid handle type
* @ingroup globus_xio_file_driver_types
* @hideinitializer
* @see GLOBUS_XIO_FILE_SET_HANDLE
*/
#define GLOBUS_XIO_FILE_INVALID_HANDLE GLOBUS_XIO_SYSTEM_INVALID_FILE
/** doxygen varargs filter stuff
* GlobusVarArgDefine(
* attr, globus_result_t, globus_xio_attr_cntl, attr, driver)
* GlobusVarArgDefine(
* handle, globus_result_t, globus_xio_handle_cntl, handle, driver)
*/
/**
* File driver specific cntls
* @ingroup globus_xio_file_driver_cntls
*/
typedef enum
{
/** GlobusVarArgEnum(attr)
* Set the file create mode.
* @ingroup globus_xio_file_driver_cntls
* Use this to set the permissions a non-existent file is created with,
* The default mode is 0644.
*
* @param mode
* A bitwise OR of all the modes desired
*
* @see globus_xio_file_mode_t
*
* string opt: mode=int
*/
/* int mode */
GLOBUS_XIO_FILE_SET_MODE,
/** GlobusVarArgEnum(attr)
* Get the file create mode.
* @ingroup globus_xio_file_driver_cntls
*
* @param mode_out
* The current mode will be stored here.
*/
/* int * mode_out */
GLOBUS_XIO_FILE_GET_MODE,
/** GlobusVarArgEnum(attr)
* Set the file open flags.
* @ingroup globus_xio_file_driver_cntls
* The default flags specify to create the file if it doesn't exist,
* open it for reading and writing, and interpret it as a binary file.
*
* @param flags
* A bitwise OR of all the flags desired
*
* @see globus_xio_file_flag_t
*
* string opt: flags=int
*/
/* int flags */
GLOBUS_XIO_FILE_SET_FLAGS,
/** GlobusVarArgEnum(attr)
* Get the file open flags.
* @ingroup globus_xio_file_driver_cntls
*
* @param flags_out
* The current flags will be stored here.
*/
/* int * flags_out */
GLOBUS_XIO_FILE_GET_FLAGS,
/** GlobusVarArgEnum(attr)
* Set the file truncate offset.
* @ingroup globus_xio_file_driver_cntls
* Use this in conjunction with the @ref GLOBUS_XIO_FILE_TRUNC flag
* to truncate a file to a non-zero offset. If the file was larger
* than offset bytes, the extra data is lost. If the file was shorter or
* non-existent, it is extended and the extended part reads as zeros.
* (default is 0)
*
* @param offset
* The desired size of the file.
*/
/* globus_off_t offset */
GLOBUS_XIO_FILE_SET_TRUNC_OFFSET,
/** GlobusVarArgEnum(attr)
* Get the file truncate offset.
* @ingroup globus_xio_file_driver_cntls
*
* @param offset_out
* The offset will be stored here.
*/
/* globus_off_t * offset_out */
GLOBUS_XIO_FILE_GET_TRUNC_OFFSET,
/** GlobusVarArgEnum(attr)
* Set the file handle to use.
* @ingroup globus_xio_file_driver_cntls
* Do not open a new file, use this pre-opened handle instead.
*
* @param handle
* Use this handle (fd or HANDLE) for the file.
* Note: close() will not be called on this handle.
*/
/* globus_xio_system_file_t handle */
GLOBUS_XIO_FILE_SET_HANDLE,
/** GlobusVarArgEnum(attr, handle)
* Get the file handle in use or in attr.
* @ingroup globus_xio_file_driver_cntls
*
* @param handle_out
* The file handle (fd or HANDLE) will be stored here. If none is set,
* GLOBUS_XIO_TCP_INVALID_HANDLE will be set.
*/
/* globus_xio_system_file_t * handle_out */
GLOBUS_XIO_FILE_GET_HANDLE,
/** GlobusVarArgEnum(attr, handle)
* Enable true blocking io when making globus_xio_read/write() calls.
* Note: use with caution. You can deadlock an entire app with this.
* @ingroup globus_xio_file_driver_cntls
*
* @param use_blocking_io
* If GLOBUS_TRUE, true blocking io will be enabled.
* GLOBUS_FALSE will disable it (default);
*/
/* globus_bool_t use_blocking_io */
GLOBUS_XIO_FILE_SET_BLOCKING_IO,
/** GlobusVarArgEnum(attr, handle)
* Get the blocking io status in use or in attr.
* @ingroup globus_xio_file_driver_cntls
*
* @param use_blocking_io_out
* The flag will be set here. GLOBUS_TRUE for enabled.
*
* string opt: blocking=bool
*/
/* globus_bool_t * use_blocking_io_out */
GLOBUS_XIO_FILE_GET_BLOCKING_IO,
/** GlobusVarArgEnum(handle)
* Reposition read/write file offset.
* @ingroup globus_xio_file_driver_cntls
*
* @param in_out_offset
* Specify the desired offset (according to whence). On success,
* the actual file offset will be stored here.
*
* @param whence
* Specify how offset should be interpreted.
*
* @see globus_xio_file_whence_t
* @see GLOBUS_XIO_SEEK
*/
/* globus_off_t * in_out_offset,
* globus_xio_file_whence_t whence */
GLOBUS_XIO_FILE_SEEK
} globus_xio_file_attr_cmd_t;
/**
* File driver open flags
* @ingroup globus_xio_file_driver_types
* @hideinitializer
* OR together all the flags you want
* @see GLOBUS_XIO_FILE_SET_FLAGS
*/
typedef enum
{
/** Create a new file if it doesn't exist (default) */
GLOBUS_XIO_FILE_CREAT = O_CREAT,
/** Fail if file already exists */
GLOBUS_XIO_FILE_EXCL = O_EXCL,
/** Open for read only */
GLOBUS_XIO_FILE_RDONLY = O_RDONLY,
/** Open for write only */
GLOBUS_XIO_FILE_WRONLY = O_WRONLY,
/** Open for reading and writing (default) */
GLOBUS_XIO_FILE_RDWR = O_RDWR,
/** Truncate file @see GLOBUS_XIO_FILE_SET_TRUNC_OFFSET */
GLOBUS_XIO_FILE_TRUNC = O_TRUNC,
/** Open file for appending */
GLOBUS_XIO_FILE_APPEND = O_APPEND,
#ifdef TARGET_ARCH_CYGWIN
GLOBUS_XIO_FILE_BINARY = O_BINARY,
GLOBUS_XIO_FILE_TEXT = O_TEXT
#else
/** File is binary (default) */
GLOBUS_XIO_FILE_BINARY = 0,
/** File is text */
GLOBUS_XIO_FILE_TEXT = 0
#endif
} globus_xio_file_flag_t;
/**
* File driver create mode
* @ingroup globus_xio_file_driver_types
* @hideinitializer
* OR these modes together to get the mode you want.
* @see GLOBUS_XIO_FILE_SET_MODE
*
* NOTE: for Win32, you only have a choice between read-only and read-write.
* If the chosen mode does not specify writing, the file will be read only
*/
typedef enum
{
/** User read, write, and execute */
GLOBUS_XIO_FILE_IRWXU = S_IRWXU,
/** User read */
GLOBUS_XIO_FILE_IRUSR = S_IRUSR,
/** User write */
GLOBUS_XIO_FILE_IWUSR = S_IWUSR,
/** User execute */
GLOBUS_XIO_FILE_IXUSR = S_IXUSR,
/** Others read, write, and execute */
GLOBUS_XIO_FILE_IRWXO = S_IRWXO,
/** Others read */
GLOBUS_XIO_FILE_IROTH = S_IROTH,
/** Others write */
GLOBUS_XIO_FILE_IWOTH = S_IWOTH,
/** Others execute */
GLOBUS_XIO_FILE_IXOTH = S_IXOTH,
/** Group read, write, and execute */
GLOBUS_XIO_FILE_IRWXG = S_IRWXG,
/** Group read */
GLOBUS_XIO_FILE_IRGRP = S_IRGRP,
/** Group write */
GLOBUS_XIO_FILE_IWGRP = S_IWGRP,
/** Group execute */
GLOBUS_XIO_FILE_IXGRP = S_IXGRP
} globus_xio_file_mode_t;
/**
* File driver seek options
* @ingroup globus_xio_file_driver_types
* @hideinitializer
* @see GLOBUS_XIO_FILE_SEEK
*/
typedef enum
{
/** set the file pointer at the specified offset */
GLOBUS_XIO_FILE_SEEK_SET = SEEK_SET,
/** set the file pointer at current position + offset */
GLOBUS_XIO_FILE_SEEK_CUR = SEEK_CUR,
/** set the file pointer at size of file + offset */
GLOBUS_XIO_FILE_SEEK_END = SEEK_END
} globus_xio_file_whence_t;
#ifdef __cplusplus
}
#endif
#endif /* GLOBUS_XIO_FILE_DRIVER_H */
globus_xio-6.6/builtins/file/PaxHeaders.22691/globus_xio_file_driver.c 0000644 0000000 0000000 00000000132 14243161125 024176 x ustar 00 0000000 0000000 30 mtime=1653400149.713966524
30 atime=1653401470.464751357
30 ctime=1653403998.865960416
globus_xio-6.6/builtins/file/globus_xio_file_driver.c 0000664 0001750 0001750 00000071226 14243161125 024346 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "globus_xio_driver.h"
#include "globus_xio_file_driver.h"
#include "version.h"
#include
GlobusDebugDefine(GLOBUS_XIO_FILE);
#define GlobusXIOFileDebugPrintf(level, message) \
GlobusDebugPrintf(GLOBUS_XIO_FILE, level, message)
#define GlobusXIOFileDebugEnter() \
GlobusXIOFileDebugPrintf( \
GLOBUS_L_XIO_FILE_DEBUG_TRACE, \
(_XIOSL("[%s] Entering\n"), _xio_name))
#define GlobusXIOFileDebugExit() \
GlobusXIOFileDebugPrintf( \
GLOBUS_L_XIO_FILE_DEBUG_TRACE, \
(_XIOSL("[%s] Exiting\n"), _xio_name))
#define GlobusXIOFileDebugExitWithError() \
GlobusXIOFileDebugPrintf( \
GLOBUS_L_XIO_FILE_DEBUG_TRACE, \
(_XIOSL("[%s] Exiting with error\n"), _xio_name))
enum globus_l_xio_error_levels
{
GLOBUS_L_XIO_FILE_DEBUG_TRACE = 1,
GLOBUS_L_XIO_FILE_DEBUG_INFO = 2
};
static
int
globus_l_xio_file_activate(void);
static
int
globus_l_xio_file_deactivate(void);
GlobusXIODefineModule(file) =
{
"globus_xio_file",
globus_l_xio_file_activate,
globus_l_xio_file_deactivate,
GLOBUS_NULL,
GLOBUS_NULL,
&local_version
};
/*
* attribute structure
*/
typedef struct
{
int mode;
int flags;
globus_off_t trunc_offset;
globus_xio_system_file_t fd;
globus_bool_t use_blocking_io;
} globus_l_attr_t;
/* default attr */
static const globus_l_attr_t globus_l_xio_file_attr_default =
{
GLOBUS_XIO_FILE_IRUSR | /* mode */
GLOBUS_XIO_FILE_IWUSR |
GLOBUS_XIO_FILE_IRGRP |
GLOBUS_XIO_FILE_IROTH,
GLOBUS_XIO_FILE_CREAT | /* flags */
GLOBUS_XIO_FILE_RDWR |
GLOBUS_XIO_FILE_BINARY,
0, /* trunc_offset */
GLOBUS_XIO_FILE_INVALID_HANDLE, /* handle */
GLOBUS_FALSE /* use_blocking_io */
};
/*
* handle structure
*/
typedef struct
{
globus_xio_system_file_handle_t system;
globus_xio_system_file_t fd;
globus_bool_t converted;
globus_bool_t use_blocking_io;
globus_mutex_t lock; /* only used to protect below */
globus_off_t file_position;
} globus_l_handle_t;
#define GlobusXIOFileGetFilePosition(handle) \
globus_l_xio_file_update_position(handle, 0, SEEK_CUR)
static
globus_off_t
globus_l_xio_file_update_position(
globus_l_handle_t * handle,
globus_off_t offset,
int whence)
{
globus_mutex_lock(&handle->lock);
{
if(whence == SEEK_SET)
{
handle->file_position = offset;
}
else if(whence == SEEK_CUR)
{
handle->file_position += offset;
}
else if(whence == SEEK_END)
{
globus_off_t size;
size = globus_xio_system_file_get_size(handle->fd);
if(size != -1)
{
handle->file_position = size;
}
handle->file_position += offset;
}
offset = handle->file_position;
}
globus_mutex_unlock(&handle->lock);
return offset;
}
/*
* initialize a driver attribute
*/
static
globus_result_t
globus_l_xio_file_attr_init(
void ** out_attr)
{
globus_l_attr_t * attr;
globus_result_t result;
GlobusXIOName(globus_l_xio_file_attr_init);
GlobusXIOFileDebugEnter();
/*
* create a file attr structure and intialize its values
*/
attr = (globus_l_attr_t *) globus_malloc(sizeof(globus_l_attr_t));
if(!attr)
{
result = GlobusXIOErrorMemory("attr");
goto error_attr;
}
memcpy(attr, &globus_l_xio_file_attr_default, sizeof(globus_l_attr_t));
*out_attr = attr;
GlobusXIOFileDebugExit();
return GLOBUS_SUCCESS;
error_attr:
GlobusXIOFileDebugExitWithError();
return result;
}
static
globus_result_t
globus_l_xio_file_string_cntl_mode(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func)
{
globus_result_t result;
unsigned int mode = 0;
int sc;
GlobusXIOName(globus_l_xio_file_string_cntl_mode);
sc = sscanf(val, "%o", &mode);
if(sc != 1 || mode > INT_MAX)
{
result = GlobusXIOErrorParse(val);
goto error;
}
result = globus_xio_string_cntl_bouncer(cntl_func, attr, cmd, (int) mode);
return result;
error:
return result;
}
static
globus_result_t
globus_l_xio_file_string_cntl_flags(
void * attr,
const char * key,
const char * val,
int cmd,
globus_xio_driver_attr_cntl_t cntl_func)
{
globus_result_t result;
int flags = 0;
if(strcmp(val, "r") == 0)
{
flags = GLOBUS_XIO_FILE_RDONLY;
}
else if(strcmp(val, "r+") == 0)
{
flags = GLOBUS_XIO_FILE_RDWR;
}
else if(strcmp(val, "w") == 0)
{
flags = GLOBUS_XIO_FILE_WRONLY |
GLOBUS_XIO_FILE_CREAT | GLOBUS_XIO_FILE_TRUNC;
}
else if(strcmp(val, "w+") == 0)
{
flags = GLOBUS_XIO_FILE_RDWR | GLOBUS_XIO_FILE_CREAT;
}
else if(strcmp(val, "a") == 0)
{
flags = GLOBUS_XIO_FILE_CREAT |
GLOBUS_XIO_FILE_WRONLY | GLOBUS_XIO_FILE_APPEND;
}
else if(strcmp(val, "a+") == 0)
{
flags = GLOBUS_XIO_FILE_CREAT
| GLOBUS_XIO_FILE_RDWR | GLOBUS_XIO_FILE_APPEND;
}
result = globus_xio_string_cntl_bouncer(cntl_func, attr, cmd, flags);
return result;
}
static
globus_result_t
globus_l_xio_file_flags_to_string(
int flags,
const char **flag_string)
{
globus_result_t result = GLOBUS_SUCCESS;
if (flags ==
(GLOBUS_XIO_FILE_CREAT
| GLOBUS_XIO_FILE_RDWR | GLOBUS_XIO_FILE_APPEND))
{
*flag_string = "a+";
}
else if (flags ==
(GLOBUS_XIO_FILE_CREAT |
GLOBUS_XIO_FILE_WRONLY | GLOBUS_XIO_FILE_APPEND))
{
*flag_string = "a";
}
else if (flags ==
(GLOBUS_XIO_FILE_RDWR | GLOBUS_XIO_FILE_CREAT))
{
*flag_string = "w+";
}
else if (flags ==
(GLOBUS_XIO_FILE_WRONLY |
GLOBUS_XIO_FILE_CREAT | GLOBUS_XIO_FILE_TRUNC))
{
*flag_string = "w";
}
else if (flags == GLOBUS_XIO_FILE_RDWR)
{
*flag_string = "r+";
}
else if (flags == GLOBUS_XIO_FILE_RDONLY)
{
*flag_string = "r";
}
else
{
result = GLOBUS_FAILURE;
}
return result;
}
static globus_xio_string_cntl_table_t file_l_string_opts_table[] =
{
{"flags", GLOBUS_XIO_FILE_SET_FLAGS,
globus_l_xio_file_string_cntl_flags},
{"mode", GLOBUS_XIO_FILE_SET_MODE,
globus_l_xio_file_string_cntl_mode},
{"blocking", GLOBUS_XIO_FILE_SET_BLOCKING_IO,
globus_xio_string_cntl_bool},
{NULL, 0, NULL}
};
/*
nk* modify the attribute structure
*/
static
globus_result_t
globus_l_xio_file_attr_cntl(
void * driver_attr,
int cmd,
va_list ap)
{
globus_l_attr_t * attr;
int * out_int;
globus_xio_system_file_t * out_fd;
globus_off_t * out_offset;
globus_bool_t * out_bool;
char **out_string;
GlobusXIOName(globus_l_xio_file_attr_cntl);
GlobusXIOFileDebugEnter();
attr = (globus_l_attr_t *) driver_attr;
switch(cmd)
{
/* int mode */
case GLOBUS_XIO_FILE_SET_MODE:
attr->mode = va_arg(ap, int);
break;
/* int * mode_out */
case GLOBUS_XIO_FILE_GET_MODE:
out_int = va_arg(ap, int *);
*out_int = attr->mode;
break;
/* int mode */
case GLOBUS_XIO_FILE_SET_FLAGS:
attr->flags = va_arg(ap, int);
break;
/* int * mode_out */
case GLOBUS_XIO_FILE_GET_FLAGS:
out_int = va_arg(ap, int *);
*out_int = attr->flags;
break;
/* globus_off_t offset */
case GLOBUS_XIO_FILE_SET_TRUNC_OFFSET:
attr->trunc_offset = va_arg(ap, globus_off_t);
break;
/* globus_off_t * offset_out */
case GLOBUS_XIO_FILE_GET_TRUNC_OFFSET:
out_offset = va_arg(ap, globus_off_t *);
*out_offset = attr->trunc_offset;
break;
/* globus_xio_system_file_t fd */
case GLOBUS_XIO_FILE_SET_HANDLE:
attr->fd = va_arg(ap, globus_xio_system_file_t);
break;
/* globus_xio_system_file_t * fd */
case GLOBUS_XIO_FILE_GET_HANDLE:
out_fd = va_arg(ap, globus_xio_system_file_t *);
*out_fd = attr->fd;
break;
/* globus_bool_t use_blocking_io */
case GLOBUS_XIO_FILE_SET_BLOCKING_IO:
attr->use_blocking_io = va_arg(ap, globus_bool_t);
break;
/* globus_bool_t * use_blocking_io */
case GLOBUS_XIO_FILE_GET_BLOCKING_IO:
out_bool = va_arg(ap, globus_bool_t *);
*out_bool = attr->use_blocking_io;
break;
case GLOBUS_XIO_GET_STRING_OPTIONS:
{
const char *opts_format = "flags=%s;mode=%03o;blocking=%s";
const char *flags_string, *blocking_string;
globus_result_t result = GLOBUS_SUCCESS;
out_string = va_arg(ap, char **);
result = globus_l_xio_file_flags_to_string(attr->flags,
&flags_string);
if (result)
{
GlobusXIOFileDebugExitWithError();
return result;
}
blocking_string = attr->use_blocking_io ? "true" : "false";
*out_string = malloc(strlen(opts_format)
+ strlen(flags_string)
+ 4
+ strlen(blocking_string));
if (!*out_string)
{
result = GlobusXIOErrorMemory("attr");
GlobusXIOFileDebugExitWithError();
return result;
}
sprintf(*out_string, opts_format,
flags_string, attr->mode, blocking_string);
}
break;
default:
GlobusXIOFileDebugExitWithError();
return GlobusXIOErrorInvalidCommand(cmd);
break;
}
GlobusXIOFileDebugExit();
return GLOBUS_SUCCESS;
}
/*
* copy an attribute structure
*/
static
globus_result_t
globus_l_xio_file_attr_copy(
void ** dst,
void * src)
{
globus_l_attr_t * attr;
globus_result_t result;
GlobusXIOName(globus_l_xio_file_attr_copy);
GlobusXIOFileDebugEnter();
attr = (globus_l_attr_t *) globus_malloc(sizeof(globus_l_attr_t));
if(!attr)
{
result = GlobusXIOErrorMemory("attr");
goto error_attr;
}
memcpy(attr, src, sizeof(globus_l_attr_t));
*dst = attr;
GlobusXIOFileDebugExit();
return GLOBUS_SUCCESS;
error_attr:
GlobusXIOFileDebugExitWithError();
return result;
}
/*
* destroy an attr structure
*/
static
globus_result_t
globus_l_xio_file_attr_destroy(
void * driver_attr)
{
GlobusXIOName(globus_l_xio_file_attr_destroy);
GlobusXIOFileDebugEnter();
free(driver_attr);
GlobusXIOFileDebugExit();
return GLOBUS_SUCCESS;
}
static
globus_result_t
globus_l_xio_file_handle_init(
globus_l_handle_t ** handle)
{
globus_result_t result;
GlobusXIOName(globus_l_xio_file_handle_init);
GlobusXIOFileDebugEnter();
*handle = (globus_l_handle_t *)
globus_calloc(1, sizeof(globus_l_handle_t));
if(!*handle)
{
result = GlobusXIOErrorMemory("handle");
goto error_handle;
}
globus_mutex_init(&(*handle)->lock, NULL);
GlobusXIOFileDebugExit();
return GLOBUS_SUCCESS;
error_handle:
GlobusXIOFileDebugExitWithError();
return result;
}
static
void
globus_l_xio_file_handle_destroy(
globus_l_handle_t * handle)
{
GlobusXIOName(globus_l_xio_file_handle_destroy);
GlobusXIOFileDebugEnter();
globus_mutex_destroy(&handle->lock);
free(handle);
GlobusXIOFileDebugExit();
}
/*
* open a file
*/
static
globus_result_t
globus_l_xio_file_open(
const globus_xio_contact_t * contact_info,
void * driver_link,
void * driver_attr,
globus_xio_operation_t op)
{
globus_l_handle_t * handle;
const globus_l_attr_t * attr;
globus_result_t result;
globus_xio_system_file_t converted_fd;
globus_bool_t converted_std = GLOBUS_FALSE;
GlobusXIOName(globus_l_xio_file_open);
GlobusXIOFileDebugEnter();
attr = (globus_l_attr_t *)
driver_attr ? driver_attr : &globus_l_xio_file_attr_default;
result = globus_l_xio_file_handle_init(&handle);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_l_xio_file_handle_init", result);
goto error_handle;
}
handle->use_blocking_io = attr->use_blocking_io;
converted_fd = attr->fd;
if(converted_fd == GLOBUS_XIO_FILE_INVALID_HANDLE &&
!contact_info->resource && contact_info->scheme)
{
converted_fd = globus_xio_system_convert_stdio(contact_info->scheme);
if(converted_fd != GLOBUS_XIO_FILE_INVALID_HANDLE)
{
converted_std = GLOBUS_TRUE;
}
}
if(converted_fd == GLOBUS_XIO_FILE_INVALID_HANDLE)
{
int flags;
globus_off_t trunc_offset = 0;
if(!contact_info->resource)
{
result = GlobusXIOErrorContactString("missing path");
goto error_pathname;
}
flags = attr->flags;
if((attr->flags & GLOBUS_XIO_FILE_TRUNC) && attr->trunc_offset > 0)
{
flags = flags & ~GLOBUS_XIO_FILE_TRUNC;
trunc_offset = attr->trunc_offset;
}
#ifdef O_LARGEFILE
flags |= O_LARGEFILE;
#endif
result = globus_xio_system_file_open(
&handle->fd, contact_info->resource, flags, attr->mode);
if(result != GLOBUS_SUCCESS)
{
goto error_open;
}
if(trunc_offset > 0)
{
result = globus_xio_system_file_truncate(
handle->fd, trunc_offset);
if(result != GLOBUS_SUCCESS)
{
goto error_truncate;
}
}
}
else
{
handle->fd = converted_fd;
handle->converted = GLOBUS_TRUE;
if(!converted_std && attr->flags & GLOBUS_XIO_FILE_TRUNC)
{
result = globus_xio_system_file_truncate(
handle->fd, attr->trunc_offset);
if(result != GLOBUS_SUCCESS)
{
goto error_truncate;
}
}
handle->file_position =
globus_xio_system_file_get_position(handle->fd);
}
result = globus_xio_system_file_init(&handle->system, handle->fd);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_xio_system_file_init", result);
goto error_init;
}
globus_xio_driver_finished_open(handle, op, GLOBUS_SUCCESS);
GlobusXIOFileDebugExit();
return GLOBUS_SUCCESS;
error_init:
error_truncate:
if(!handle->converted)
{
globus_xio_system_file_close(handle->fd);
}
error_open:
if(handle->converted)
{
result = GlobusXIOErrorWrapFailedWithMessage(result,
"Unable to convert file handle %ld", (long) handle->fd);
}
else
{
result = GlobusXIOErrorWrapFailedWithMessage(result,
"Unable to open file %s", contact_info->resource);
}
error_pathname:
globus_l_xio_file_handle_destroy(handle);
error_handle:
GlobusXIOFileDebugExitWithError();
return result;
}
/*
* close a file
*/
static
globus_result_t
globus_l_xio_file_close(
void * driver_specific_handle,
void * attr,
globus_xio_operation_t op)
{
globus_l_handle_t * handle;
globus_result_t res = GLOBUS_SUCCESS;
GlobusXIOName(globus_l_xio_file_close);
GlobusXIOFileDebugEnter();
handle = (globus_l_handle_t *) driver_specific_handle;
globus_xio_system_file_destroy(handle->system);
if(!handle->converted)
{
res = globus_xio_system_file_close(handle->fd);
}
globus_xio_driver_finished_close(op, res);
globus_l_xio_file_handle_destroy(handle);
GlobusXIOFileDebugExit();
return GLOBUS_SUCCESS;
}
static
void
globus_l_xio_file_system_read_cb(
globus_result_t result,
globus_size_t nbytes,
void * user_arg)
{
globus_xio_operation_t op;
GlobusXIOName(globus_l_xio_file_system_read_cb);
GlobusXIOFileDebugEnter();
op = (globus_xio_operation_t) user_arg;
globus_l_xio_file_update_position(
(globus_l_handle_t *) globus_xio_operation_get_driver_specific(op),
nbytes,
SEEK_CUR);
globus_xio_driver_finished_read(op, result, nbytes);
GlobusXIOFileDebugExit();
}
/*
* read from a file
*/
static
globus_result_t
globus_l_xio_file_read(
void * driver_specific_handle,
const globus_xio_iovec_t * iovec,
int iovec_count,
globus_xio_operation_t op)
{
globus_l_handle_t * handle;
globus_size_t nbytes;
globus_result_t result;
globus_off_t offset;
GlobusXIOName(globus_l_xio_file_read);
GlobusXIOFileDebugEnter();
handle = (globus_l_handle_t *) driver_specific_handle;
result = globus_xio_driver_data_descriptor_cntl(
op, NULL, GLOBUS_XIO_DD_GET_OFFSET, &offset);
if(result != GLOBUS_SUCCESS || offset == -1)
{
offset = GlobusXIOFileGetFilePosition(handle);
}
else
{
globus_l_xio_file_update_position(handle, offset, SEEK_SET);
}
GlobusXIOFileDebugPrintf(
GLOBUS_L_XIO_FILE_DEBUG_INFO,
("[%s] count=%d, 1st buflen=%d offset=%" GLOBUS_OFF_T_FORMAT "\n",
_xio_name, iovec_count, (int) iovec[0].iov_len, offset));
/* if buflen and waitfor are both 0, we behave like register select */
if((globus_xio_operation_get_wait_for(op) == 0 &&
(iovec_count > 1 || iovec[0].iov_len > 0)) ||
(handle->use_blocking_io &&
globus_xio_driver_operation_is_blocking(op)))
{
result = globus_xio_system_file_read(
handle->system,
offset,
iovec,
iovec_count,
globus_xio_operation_get_wait_for(op),
&nbytes);
globus_l_xio_file_update_position(handle, nbytes, SEEK_CUR);
globus_xio_driver_finished_read(op, result, nbytes);
result = GLOBUS_SUCCESS;
}
else
{
result = globus_xio_system_file_register_read(
op,
handle->system,
offset,
iovec,
iovec_count,
globus_xio_operation_get_wait_for(op),
globus_l_xio_file_system_read_cb,
op);
}
GlobusXIOFileDebugExit();
return result;
}
static
void
globus_l_xio_file_system_write_cb(
globus_result_t result,
globus_size_t nbytes,
void * user_arg)
{
globus_xio_operation_t op;
GlobusXIOName(globus_l_xio_file_system_write_cb);
GlobusXIOFileDebugEnter();
op = (globus_xio_operation_t) user_arg;
globus_l_xio_file_update_position(
(globus_l_handle_t *) globus_xio_operation_get_driver_specific(op),
nbytes,
SEEK_CUR);
globus_xio_driver_finished_write(op, result, nbytes);
GlobusXIOFileDebugExit();
}
/*
* write to a file
*/
static
globus_result_t
globus_l_xio_file_write(
void * driver_specific_handle,
const globus_xio_iovec_t * iovec,
int iovec_count,
globus_xio_operation_t op)
{
globus_l_handle_t * handle;
globus_size_t nbytes;
globus_result_t result;
globus_off_t offset;
GlobusXIOName(globus_l_xio_file_write);
GlobusXIOFileDebugEnter();
handle = (globus_l_handle_t *) driver_specific_handle;
result = globus_xio_driver_data_descriptor_cntl(
op, NULL, GLOBUS_XIO_DD_GET_OFFSET, &offset);
if(result != GLOBUS_SUCCESS || offset == -1)
{
offset = GlobusXIOFileGetFilePosition(handle);
}
else
{
globus_l_xio_file_update_position(handle, offset, SEEK_SET);
}
GlobusXIOFileDebugPrintf(
GLOBUS_L_XIO_FILE_DEBUG_INFO,
("[%s] count=%d, 1st buflen=%d offset=%" GLOBUS_OFF_T_FORMAT "\n",
_xio_name, iovec_count, (int) iovec[0].iov_len, offset));
/* if buflen and waitfor are both 0, we behave like register select */
if((globus_xio_operation_get_wait_for(op) == 0 &&
(iovec_count > 1 || iovec[0].iov_len > 0)) ||
(handle->use_blocking_io &&
globus_xio_driver_operation_is_blocking(op)))
{
result = globus_xio_system_file_write(
handle->system,
offset,
iovec,
iovec_count,
globus_xio_operation_get_wait_for(op),
&nbytes);
globus_l_xio_file_update_position(handle, nbytes, SEEK_CUR);
globus_xio_driver_finished_write(op, result, nbytes);
result = GLOBUS_SUCCESS;
}
else
{
result = globus_xio_system_file_register_write(
op,
handle->system,
offset,
iovec,
iovec_count,
globus_xio_operation_get_wait_for(op),
globus_l_xio_file_system_write_cb,
op);
}
GlobusXIOFileDebugExit();
return result;
}
static
globus_result_t
globus_l_xio_file_cntl(
void * driver_specific_handle,
int cmd,
va_list ap)
{
globus_result_t result = GLOBUS_SUCCESS;
globus_l_handle_t * handle;
globus_xio_system_file_t * out_fd;
globus_off_t * offset;
globus_off_t in_offset;
int whence;
globus_bool_t * out_bool;
GlobusXIOName(globus_l_xio_file_cntl);
GlobusXIOFileDebugEnter();
handle = (globus_l_handle_t *) driver_specific_handle;
switch(cmd)
{
/* globus_off_t * in_out_offset */
/* globus_xio_file_whence_t whence */
case GLOBUS_XIO_FILE_SEEK:
offset = va_arg(ap, globus_off_t *);
whence = va_arg(ap, int);
*offset = globus_l_xio_file_update_position(handle, *offset, whence);
break;
/* globus_off_t offset */
case GLOBUS_XIO_SEEK:
in_offset = va_arg(ap, globus_off_t);
globus_l_xio_file_update_position(handle, in_offset, SEEK_SET);
break;
/* globus_xio_system_file_t * handle */
case GLOBUS_XIO_FILE_GET_HANDLE:
out_fd = va_arg(ap, globus_xio_system_file_t *);
*out_fd = handle->fd;
break;
/* globus_bool_t use_blocking_io */
case GLOBUS_XIO_FILE_SET_BLOCKING_IO:
handle->use_blocking_io = va_arg(ap, globus_bool_t);
break;
/* globus_bool_t * use_blocking_io */
case GLOBUS_XIO_FILE_GET_BLOCKING_IO:
out_bool = va_arg(ap, globus_bool_t *);
*out_bool = handle->use_blocking_io;
break;
default:
result = GlobusXIOErrorInvalidCommand(cmd);
break;
}
GlobusXIOFileDebugExit();
return result;
}
static
globus_result_t
globus_l_xio_file_init(
globus_xio_driver_t * out_driver)
{
globus_xio_driver_t driver;
globus_result_t result;
GlobusXIOName(globus_l_xio_file_init);
GlobusXIOFileDebugEnter();
/* I don't support any driver options, so I'll ignore the ap */
result = globus_xio_driver_init(&driver, "file", GLOBUS_NULL);
if(result != GLOBUS_SUCCESS)
{
result = GlobusXIOErrorWrapFailed(
"globus_l_xio_file_handle_init", result);
goto error_init;
}
globus_xio_driver_set_transport(
driver,
globus_l_xio_file_open,
globus_l_xio_file_close,
globus_l_xio_file_read,
globus_l_xio_file_write,
globus_l_xio_file_cntl);
globus_xio_driver_set_attr(
driver,
globus_l_xio_file_attr_init,
globus_l_xio_file_attr_copy,
globus_l_xio_file_attr_cntl,
globus_l_xio_file_attr_destroy);
globus_xio_driver_string_cntl_set_table(
driver,
file_l_string_opts_table);
*out_driver = driver;
GlobusXIOFileDebugExit();
return GLOBUS_SUCCESS;
error_init:
GlobusXIOFileDebugExitWithError();
return result;
}
static
void
globus_l_xio_file_destroy(
globus_xio_driver_t driver)
{
GlobusXIOName(globus_l_xio_file_destroy);
GlobusXIOFileDebugEnter();
globus_xio_driver_destroy(driver);
GlobusXIOFileDebugExit();
}
GlobusXIODefineDriver(
file,
globus_l_xio_file_init,
globus_l_xio_file_destroy);
static
int
globus_l_xio_file_activate(void)
{
int rc;
GlobusXIOName(globus_l_xio_file_activate);
GlobusDebugInit(GLOBUS_XIO_FILE, TRACE INFO);
GlobusXIOFileDebugEnter();
rc = globus_module_activate(GLOBUS_XIO_SYSTEM_MODULE);
if(rc != GLOBUS_SUCCESS)
{
goto error_activate;
}
GlobusXIORegisterDriver(file);
GlobusXIOFileDebugExit();
return GLOBUS_SUCCESS;
error_activate:
GlobusXIOFileDebugExitWithError();
GlobusDebugDestroy(GLOBUS_XIO_FILE);
return rc;
}
static
int
globus_l_xio_file_deactivate(void)
{
GlobusXIOName(globus_l_xio_file_deactivate);
GlobusXIOFileDebugEnter();
GlobusXIOUnRegisterDriver(file);
globus_module_deactivate(GLOBUS_XIO_SYSTEM_MODULE);
GlobusXIOFileDebugExit();
GlobusDebugDestroy(GLOBUS_XIO_FILE);
return GLOBUS_SUCCESS;
}
globus_xio-6.6/builtins/PaxHeaders.22691/http 0000644 0000000 0000000 00000000132 14243170536 017277 x ustar 00 0000000 0000000 30 mtime=1653403998.946959644
30 atime=1653403999.531954065
30 ctime=1653403998.946959644
globus_xio-6.6/builtins/http/ 0000775 0001750 0001750 00000000000 14243170536 017514 5 ustar 00johndoe johndoe 0000000 0000000 globus_xio-6.6/builtins/http/PaxHeaders.22691/Makefile.in 0000644 0000000 0000000 00000000132 14243161507 021417 x ustar 00 0000000 0000000 30 mtime=1653400391.951511957
30 atime=1653401061.061802181
30 ctime=1653403998.920959892
globus_xio-6.6/builtins/http/Makefile.in 0000664 0001750 0001750 00000053721 14243161507 021567 0 ustar 00johndoe johndoe 0000000 0000000 # Makefile.in generated by automake 1.13.4 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = builtins/http
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/build-aux/depcomp $(include_HEADERS) \
$(noinst_HEADERS)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/dirt.sh $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/globus_i_xio_config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libglobus_xio_http_driver_la_LIBADD =
am_libglobus_xio_http_driver_la_OBJECTS = globus_xio_http.lo \
globus_xio_http_attr.lo globus_xio_http_client.lo \
globus_xio_http_handle.lo globus_xio_http_header.lo \
globus_xio_http_header_info.lo globus_xio_http_request.lo \
globus_xio_http_response.lo globus_xio_http_rfc2616.lo \
globus_xio_http_server.lo globus_xio_http_target.lo \
globus_xio_http_transform.lo
libglobus_xio_http_driver_la_OBJECTS = \
$(am_libglobus_xio_http_driver_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(libglobus_xio_http_driver_la_SOURCES)
DIST_SOURCES = $(libglobus_xio_http_driver_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
test -z "$$files" \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
am__installdirs = "$(DESTDIR)$(includedir)"
HEADERS = $(include_HEADERS) $(noinst_HEADERS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AGE_VERSION = @AGE_VERSION@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AS = @AS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BUILTIN_EXTENSIONS_DEC = @BUILTIN_EXTENSIONS_DEC@
BUILTIN_EXTENSIONS_DEF = @BUILTIN_EXTENSIONS_DEF@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DIRT_BRANCH_ID = @DIRT_BRANCH_ID@
DIRT_TIMESTAMP = @DIRT_TIMESTAMP@
DLLTOOL = @DLLTOOL@
DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GLOBUS_COMMON_CFLAGS = @GLOBUS_COMMON_CFLAGS@
GLOBUS_COMMON_LIBS = @GLOBUS_COMMON_LIBS@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAJOR_VERSION = @MAJOR_VERSION@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MINOR_VERSION = @MINOR_VERSION@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_DEPS = @PACKAGE_DEPS@
PACKAGE_DEP_CFLAGS = @PACKAGE_DEP_CFLAGS@
PACKAGE_DEP_LIBS = @PACKAGE_DEP_LIBS@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
XIO_BUILTIN_DIRS = @XIO_BUILTIN_DIRS@
XIO_BUILTIN_LIBS = @XIO_BUILTIN_LIBS@
XIO_BUILTIN_PC_INCLUDES = @XIO_BUILTIN_PC_INCLUDES@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
include_HEADERS = \
globus_xio_http.h
noinst_HEADERS = \
globus_i_xio_http.h \
globus_i_xio_http_responses.h
noinst_LTLIBRARIES = libglobus_xio_http_driver.la
AM_CPPFLAGS = -I$(top_srcdir) -DGLOBUS_BUILTIN=1 $(PACKAGE_DEP_CFLAGS)
AM_LDFLAGS = $(PACKAGE_DEP_LIBS)
libglobus_xio_http_driver_la_SOURCES = \
globus_xio_http.c \
globus_xio_http_attr.c \
globus_xio_http_client.c \
globus_xio_http_handle.c \
globus_xio_http_header.c \
globus_xio_http_header_info.c \
globus_xio_http_request.c \
globus_xio_http_response.c \
globus_xio_http_rfc2616.c \
globus_xio_http_server.c \
globus_xio_http_target.c \
globus_xio_http_transform.c \
globus_i_xio_http_responses.h \
globus_i_xio_http.h \
globus_xio_http.h
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign builtins/http/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign builtins/http/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
test -z "$$locs" || { \
echo rm -f $${locs}; \
rm -f $${locs}; \
}
libglobus_xio_http_driver.la: $(libglobus_xio_http_driver_la_OBJECTS) $(libglobus_xio_http_driver_la_DEPENDENCIES) $(EXTRA_libglobus_xio_http_driver_la_DEPENDENCIES)
$(AM_V_CCLD)$(LINK) $(libglobus_xio_http_driver_la_OBJECTS) $(libglobus_xio_http_driver_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globus_xio_http.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globus_xio_http_attr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globus_xio_http_client.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globus_xio_http_handle.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globus_xio_http_header.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globus_xio_http_header_info.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globus_xio_http_request.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globus_xio_http_response.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globus_xio_http_rfc2616.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globus_xio_http_server.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globus_xio_http_target.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globus_xio_http_transform.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
install-includeHEADERS: $(include_HEADERS)
@$(NORMAL_INSTALL)
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
$(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
$(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
done
uninstall-includeHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES) $(HEADERS)
installdirs:
for dir in "$(DESTDIR)$(includedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am: install-includeHEADERS
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-includeHEADERS
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
ctags-am distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am \
install-includeHEADERS install-info install-info-am \
install-man install-pdf install-pdf-am install-ps \
install-ps-am install-strip installcheck installcheck-am \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
uninstall-am uninstall-includeHEADERS
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
globus_xio-6.6/builtins/http/PaxHeaders.22691/Makefile.am 0000644 0000000 0000000 00000000132 14243161125 021402 x ustar 00 0000000 0000000 30 mtime=1653400149.713966524
30 atime=1653400391.910512372
30 ctime=1653403998.922959873
globus_xio-6.6/builtins/http/Makefile.am 0000664 0001750 0001750 00000001411 14243161125 021537 0 ustar 00johndoe johndoe 0000000 0000000 include_HEADERS = \
globus_xio_http.h
noinst_HEADERS = \
globus_i_xio_http.h \
globus_i_xio_http_responses.h
noinst_LTLIBRARIES = libglobus_xio_http_driver.la
AM_CPPFLAGS = -I$(top_srcdir) -DGLOBUS_BUILTIN=1 $(PACKAGE_DEP_CFLAGS)
AM_LDFLAGS = $(PACKAGE_DEP_LIBS)
libglobus_xio_http_driver_la_SOURCES = \
globus_xio_http.c \
globus_xio_http_attr.c \
globus_xio_http_client.c \
globus_xio_http_handle.c \
globus_xio_http_header.c \
globus_xio_http_header_info.c \
globus_xio_http_request.c \
globus_xio_http_response.c \
globus_xio_http_rfc2616.c \
globus_xio_http_server.c \
globus_xio_http_target.c \
globus_xio_http_transform.c \
globus_i_xio_http_responses.h \
globus_i_xio_http.h \
globus_xio_http.h
globus_xio-6.6/builtins/http/PaxHeaders.22691/globus_xio_http.h 0000644 0000000 0000000 00000000132 14243161125 022730 x ustar 00 0000000 0000000 30 mtime=1653400149.714966514
30 atime=1653401472.191734269
30 ctime=1653403998.923959863
globus_xio-6.6/builtins/http/globus_xio_http.h 0000664 0001750 0001750 00000043114 14243161125 023073 0 ustar 00johndoe johndoe 0000000 0000000 /*
* Copyright 1999-2006 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if !defined GLOBUS_XIO_DRIVER_HTTP_H
#define GLOBUS_XIO_DRIVER_HTTP_H 1
/**
* @file globus_xio_http.h
* @brief Globus XIO HTTP Driver Header
*/
#include "globus_xio.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup globus_xio_http_driver Globus XIO HTTP Driver
* @ingroup globus_xio
* @brief Globus XIO HTTP Driver
*
* This driver implements the HTTP/1.0 and HTTP/1.1 protocols within
* the Globus XIO framework. It may be used with the tcp driver for
* the standard HTTP protocol stack, or may be combined with the gsi
* driver for a HTTPS implementation.
*
* This implementation supports user-defined HTTP headers, persistent
* connections, and chunked transfer encoding.
*/
/**
* @defgroup globus_xio_http_driver_instance Opening/Closing
* @ingroup globus_xio_http_driver
* @brief Opening/Closing
*
* An XIO handle with the http driver can be created with either
* @ref globus_xio_handle_create() or
* @ref globus_xio_server_register_accept().
*
* If the handle is created with
* @ref globus_xio_server_register_accept(), then an HTTP service handle
* will be created when @ref globus_xio_register_open() is called. The XIO
* application must call one of the functions in the @ref globus_xio_read()
* family to receive the HTTP request metadata. This metadata will be returned
* in the data descriptor associated with that first read: the application
* should use the GLOBUS_XIO_HTTP_GET_REQUEST descriptor cntl to extract
* this metadata.
*
* If the handle is created with @ref globus_xio_handle_create(), then
* an HTTP client handle will be created when
* @ref globus_xio_register_open() is called. HTTP request headers, version and
* method may be chosen by setting attributes.
*/
/**
* @defgroup globus_xio_http_driver_io Reading/Writing
* @ingroup globus_xio_http_driver
* @brief Reading/Writing
*
* The HTTP driver behaves similar to the underlying transport driver
* with respect to reads and writes with the exception that metadata must
* be passed to the handle via open attributes on the client side and will
* be received as data descriptors as part of the first request read or
* response read.
*/
/**
* @defgroup globus_xio_http_driver_server Server
* @ingroup globus_xio_http_driver
* @brief Server
*
* The @ref globus_xio_server_create() causes a new transport-specific
* listener socket to be created to handle new HTTP connections.
* @ref globus_xio_server_register_accept() will accept a new
* connection for processing. @ref globus_xio_server_register_close()
* cleans up the internal resources associated with the http server
* and calls close on the listener.
*
* Multiple HTTP requests may be read in sequence from an HTTP
* server. After each request is processed and the response is sent (either by
* writing the entire entity body as specified by the Content-Length header or
* by using the GLOBUS_XIO_HTTP_HANDLE_SET_END_OF_ENTITY handle cntl), the next
* read will contain the metadata related to the next operation.
* Only one request will be in process at once--the previous request must have
* sent or received and EOF (whichever is applicable to the request type).
*/
/**
* @defgroup globus_xio_http_driver_cntls Attributes and Cntls
* @ingroup globus_xio_http_driver
* @brief Attributes and Cntls
*
* HTTP driver specific attrs and cntls.
*
* @see globus_xio_attr_cntl()
* @see globus_xio_handle_cntl()
*/
/**
* @defgroup globus_xio_http_driver_errors Error Types
* @ingroup globus_xio_http_driver
* @brief Error Types
*
* In addition to errors generated by underlying protocol drivers, the XIO
* HTTP driver defines a few error conditions specific to the HTTP protocol.
*
* @see globus_xio_driver_error_match()
*/
/** doxygen varargs filter stuff
* GlobusVarArgDefine(
* attr, globus_result_t, globus_xio_attr_cntl, attr, driver)
* GlobusVarArgDefine(
* handle, globus_result_t, globus_xio_handle_cntl, handle, driver)
* GlobusVarArgDefine(
* dd, globus_result_t, globus_xio_data_descriptor_cntl, dd, driver)
*/
/**
* @brief HTTP Header
* @ingroup globus_xio_http_driver
*/
typedef struct
{
/** Header Name */
char * name;
/** Header Value */
char * value;
}
globus_xio_http_header_t;
/**
* HTTP driver specific cntls
* @ingroup globus_xio_http_driver_cntls
*/
typedef enum
{
/**
* GlobusVarArgEnum(handle)
* Set the value of a response HTTP header.
* @ingroup globus_xio_http_driver_cntls
*
* @param header_name
* Name of the HTTP header to set.
* @param header_value
* Value of the HTTP header
*
* Certain headers will cause changes in how the HTTP protocol will
* be handled. These include:
* - Transfer-Encoding: {identity|chunked}
* Override the default transfer encoding. If a server knows the
* exact length of the message body, or does not intend to support
* persistent connections, it may set this header to be
* "identity".
* If this is set to "identity" and any of the following are true, then
* the connection will be closed after the end of the response is sent:
*
* - A Content-Length header is not present
* - The HTTP version is set to "HTTP/1.0"
* - The Connection header is set to "close"
* Attempts to set this to "chunked" with an "HTTP/1.0" client will
* fail with a GLOBUS_XIO_ERROR_HTTP_INVALID_HEADER error.
* - Content-Length: 1*Digit
* - Provide a content length for the response message. If the
* "chunked" transfer encoding is being used, then this header
* will be silently ignored by the HTTP driver.
* - Connection: close
* - The HTTP connection will be closed after the end of the data
* response is written.
*
* @return This handle control function can fail with
* - GLOBUS_XIO_ERROR_MEMORY
* - GLOBUS_XIO_ERROR_PARAMETER
* - GLOBUS_XIO_ERROR_HTTP_INVALID_HEADER
*/
/* const char * header_name,
const char * header_value */
GLOBUS_XIO_HTTP_HANDLE_SET_RESPONSE_HEADER,
/** GlobusVarArgEnum(handle)
* Set the response status code.
* @ingroup globus_xio_http_driver_cntls
*
* @param status
* Value in the range 100-599 which will be used as the HTTP response
* code, as per RFC 2616.
*
* If this cntl is not called by a server, then
* the default value of 200 ("Ok") will be used. If this is called on the
* client-side of an HTTP connection, the handle control will fail with a
* GLOBUS_XIO_ERROR_PARAMETER error.
*
* @return This handle control function can fail with
* - GLOBUS_XIO_ERROR_PARAMETER
*/
/* int status */
GLOBUS_XIO_HTTP_HANDLE_SET_RESPONSE_STATUS_CODE,
/** GlobusVarArgEnum(handle)
* Set the response reason phrase.
* @ingroup globus_xio_http_driver_cntls
*
* @param reason
* The value of the HTTP response string, as per RFC 2616.
*
* If this cntl is not called by a server, then a default value based on
* the handle's response status code will be generated. If this is called
* on the client-side of an HTTP connection, the handle control will fail
* with a GLOBUS_XIO_ERROR_PARAMETER error.
*
* @return This handle control function can fail with
* - GLOBUS_XIO_ERROR_MEMORY
* - GLOBUS_XIO_ERROR_PARAMETER
*/
/* const char * reason */
GLOBUS_XIO_HTTP_HANDLE_SET_RESPONSE_REASON_PHRASE,
/** GlobusVarArgEnum(handle)
* Set the response HTTP version.
* @ingroup globus_xio_http_driver_cntls
*
* @param version
* The HTTP version to be used in the server response line.
*
* If this cntl is not called by a server, then the default of
* GLOBUS_XIO_HTTP_VERSION_1_1 will be used, though no HTTP/1.1 features
* (chunking, persistent connections, etc) will be
* assumed if the client request was an HTTP/1.0 request. If this is
* called on the client-side of an HTTP connection, the handle control
* will fail with GLOBUS_XIO_ERROR_PARAMETER.
*
* @return This handle control function can fail with
* - GLOBUS_XIO_ERROR_MEMORY
* - GLOBUS_XIO_ERROR_PARAMETER
*/
/* globus_xio_http_version_t version */
GLOBUS_XIO_HTTP_HANDLE_SET_RESPONSE_HTTP_VERSION,
/** GlobusVarArgEnum(handle)
* Indicate end-of-entity for an HTTP body.
* @ingroup globus_xio_http_driver_cntls
*
* HTTP clients and servers must call this command to indicate to the
* driver that the entity-body which is being sent is completed.
* Subsequent attempts to write data on the handle will fail.
*
* This handle command MUST be called on the client side of an HTTP
* connection when the HTTP method is OPTIONS, POST, or PUT, or when
* the open attributes indicate that an entity will be sent. This handle
* command MUST be called on the server side of an HTTP request connection
* when the HTTP method was OPTIONS, GET, POST, or TRACE.
*/
GLOBUS_XIO_HTTP_HANDLE_SET_END_OF_ENTITY,
GLOBUS_XIO_HTTP_HANDLE_SET_REQUEST_HEADER
}
globus_xio_http_handle_cmd_t;
/**
* HTTP driver specific attribute and data descriptor cntls
* @ingroup globus_xio_http_driver_cntls
*/
typedef enum
{
/** GlobusVarArgEnum(attr)
* Set the HTTP method to use for a client request.
* @ingroup globus_xio_http_driver_cntls
*
* @param method
* The request method string ("GET", "PUT", "POST", etc) that will
* be used in the HTTP request.
*
* If this is not set on the target before it is opened, it will default
* to GET.
*
* This attribute is ignored when opening the server side of an HTTP
* connection.
*
* Setting this attribute may fail with
* - GLOBUS_XIO_ERROR_MEMORY
* - GLOBUS_XIO_ERROR_PARAMETER
*/
/* const char * method */
GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_METHOD,
/** GlobusVarArgEnum(attr)
* Set the HTTP version to use for a client request.
* @ingroup globus_xio_http_driver_cntls
*
* @param version
* The HTTP version to use for the client request.
*
* If the client is using HTTP/1.0 in a request which will send a
* request message body (such as a POST or PUT), then the client MUST set
* the "Content-Length" HTTP header to be the length of the message. If
* this attribute is not present, then the default of
* GLOBUS_XIO_HTTP_VERSION_1_1 will be used.
*
* This attribute is ignored when opening the server side of an HTTP
* connection.
*/
/* globus_xio_http_version_t version */
GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_HTTP_VERSION,
/** GlobusVarArgEnum(attr)
* Set the value of an HTTP request header.
* @ingroup globus_xio_http_driver_cntls
*
* @param header_name
* Name of the HTTP header to set.
* @param header_value
* Value of the HTTP header
*
* Certain headers will cause the HTTP driver to behave differently than
* normal. This must be called before
*
* - Transfer-Encoding: {identity|chunked}
* Override the default transfer encoding. If a server knows the
* exact length of the message body, or does not intend to support
* persistent connections, it may set this header to be
* "identity".
* If this is set to "identity" and any of the following are true, then
* the connection will be closed after the end of the message is sent:
*