/* * Function: globus_gass_transfer_fail() * * Description: User-triggered error. Signal failure to the * protocol module, and call any oustanding callbacks * * Parameters: * * Returns: */ int globus_gass_transfer_fail( globus_gass_transfer_request_t request, globus_gass_transfer_callback_t callback, void * callback_arg) { globus_gass_transfer_request_struct_t * req; int rc = GLOBUS_SUCCESS; globus_i_gass_transfer_lock(); req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; goto finish; } if(callback == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_NULL_POINTER; goto finish; } rc = globus_i_gass_transfer_fail(request, req, callback, callback_arg); finish: globus_i_gass_transfer_unlock(); return rc; }
/** * Destroy a request handle. * @ingroup globus_gass_transfer_request * * This function destroys the caller's reference to a request handle. * It must be called for all request handles which are created by calling * functions in the "@ref globus_gass_transfer_client" or * "@ref globus_gass_transfer_server" sections of this manual. * After calling the function, the caller must not attempt to use the * request handle for any purpose. * * @param request * The request to destroy. * @retval GLOBUS_SUCCESS * The request handle reference was successfully destroyed. * @retval GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE * Either an invalid request handle or one which is actively being * used was passed to this function as the @a request parameter. */ int globus_gass_transfer_request_destroy( globus_gass_transfer_request_t request) { globus_gass_transfer_request_struct_t * req; int rc; globus_i_gass_transfer_lock(); req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; goto finish; } if(req->status != GLOBUS_GASS_TRANSFER_REQUEST_FAILED && req->status != GLOBUS_GASS_TRANSFER_REQUEST_DONE && req->status != GLOBUS_GASS_TRANSFER_REQUEST_FINISHING && req->status != GLOBUS_GASS_TRANSFER_REQUEST_FAILING && req->status != GLOBUS_GASS_TRANSFER_REQUEST_REFERRED && req->status != GLOBUS_GASS_TRANSFER_REQUEST_REFERRING && req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING && req->status != GLOBUS_GASS_TRANSFER_REQUEST_DENIED) { rc = GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; goto finish; } rc = globus_i_gass_transfer_request_destroy(request); finish: globus_i_gass_transfer_unlock(); return rc; }
/* * Function: globus_i_gass_transfer_send_disaptcher() * * Description: if the head of the pending fifo should be * sent over, send it. * * Parameters: * * Returns: */ void globus_i_gass_transfer_send_dispatcher( globus_gass_transfer_request_t request) { globus_gass_transfer_pending_t * head; globus_gass_transfer_request_struct_t * req; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { return; } /* If we are not in the PENDING state, we should not look at the queue */ if(req->status != GLOBUS_GASS_TRANSFER_REQUEST_PENDING) { return; } /* If the fifo is empty, there is nothing to do */ if(globus_fifo_empty(&req->pending_data)) { return; } head = globus_fifo_peek(&req->pending_data); if(head->pending == GLOBUS_TRUE) { /* * If the first in the fifo has already been sent to * the protocol module, there is nothing to do */ return; } else { head->pending = GLOBUS_TRUE; req->status = GLOBUS_GASS_TRANSFER_REQUEST_ACTING; globus_i_gass_transfer_unlock(); req->proto->send_buffer(req->proto, request, head->bytes, head->length, head->last_data); globus_i_gass_transfer_lock(); } }
static void globus_l_gass_transfer_operation_complete( globus_gass_transfer_request_t request, globus_byte_t * bytes, globus_size_t nbytes, globus_bool_t failed, globus_bool_t last_data, globus_gass_transfer_dispatch_func_t dispatcher) { globus_gass_transfer_request_struct_t * req; globus_gass_transfer_pending_t * head; globus_gass_transfer_callback_t fail_callback=GLOBUS_NULL; void * callback_arg; globus_i_gass_transfer_lock(); req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { goto finish; } switch(req->status) { case GLOBUS_GASS_TRANSFER_REQUEST_ACTING: if(! last_data) { /* * normal operation, go back to pending state, callback * to user */ req->status = GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING; while(req->status == GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING || ( (req->status == GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING || req->status == GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING) && !globus_fifo_empty(&req->pending_data))) { head = globus_fifo_dequeue(&req->pending_data); /* Call back to user */ globus_i_gass_transfer_unlock(); head->callback(head->callback_arg, request, head->bytes, nbytes, last_data); globus_i_gass_transfer_lock(); nbytes = 0; last_data = GLOBUS_TRUE; globus_free(head); if(req->status == GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING) { req->status = GLOBUS_GASS_TRANSFER_REQUEST_PENDING; } } if(req->status == GLOBUS_GASS_TRANSFER_REQUEST_PENDING) { /* dispatch next, if available */ dispatcher(request); break; } else if(req->status == GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING) { req->status = GLOBUS_GASS_TRANSFER_REQUEST_FAILED; fail_callback = req->fail_callback; callback_arg = req->fail_callback_arg; /* free up references to request and proto */ req->proto->destroy(req->proto, request); /* free up the GASS's reference to this request */ globus_i_gass_transfer_request_destroy(request); globus_i_gass_transfer_unlock(); if(fail_callback != GLOBUS_NULL) { fail_callback(callback_arg, request); } return; } } else { /* failed or done */ if(failed) { req->status = GLOBUS_GASS_TRANSFER_REQUEST_FAILING; last_data = GLOBUS_TRUE; } else { req->status = GLOBUS_GASS_TRANSFER_REQUEST_FINISHING; } while(!globus_fifo_empty(&req->pending_data)) { head = globus_fifo_dequeue(&req->pending_data); /* Call back to user */ globus_i_gass_transfer_unlock(); head->callback(head->callback_arg, request, head->bytes, nbytes, last_data); globus_i_gass_transfer_lock(); nbytes = 0; globus_free(head); } fail_callback = req->fail_callback; callback_arg = req->fail_callback_arg; /* free up references to request and proto */ req->proto->destroy(req->proto, request); /* free up the proto's and GASS's reference to this request */ globus_i_gass_transfer_request_destroy(request); if(globus_i_gass_transfer_deactivating) { globus_i_gass_transfer_request_destroy(request); } globus_i_gass_transfer_unlock(); if(fail_callback != GLOBUS_NULL) { fail_callback(callback_arg, request); } return; } break; case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING: req->status = GLOBUS_GASS_TRANSFER_REQUEST_FAILING; last_data = GLOBUS_TRUE; while(!globus_fifo_empty(&req->pending_data)) { head = globus_fifo_dequeue(&req->pending_data); /* Call back to user */ globus_i_gass_transfer_unlock(); head->callback(head->callback_arg, request, head->bytes, nbytes, last_data); globus_free(head); nbytes = 0; globus_i_gass_transfer_lock(); } fail_callback = req->fail_callback; callback_arg = req->fail_callback_arg; /* free up references to request and proto */ req->proto->destroy(req->proto, request); /* free up the proto's and GASS's reference to this request */ globus_i_gass_transfer_request_destroy(request); globus_i_gass_transfer_unlock(); fail_callback(callback_arg, request); return; case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING: req->status = GLOBUS_GASS_TRANSFER_REQUEST_REFERRING; last_data = GLOBUS_TRUE; while(!globus_fifo_empty(&req->pending_data)) { head = globus_fifo_dequeue(&req->pending_data); /* Call back to user */ globus_i_gass_transfer_unlock(); head->callback(head->callback_arg, request, head->bytes, nbytes, last_data); globus_free(head); nbytes = 0; globus_i_gass_transfer_lock(); } /* free up references to request and proto */ req->proto->destroy(req->proto, request); /* free up the proto's and GASS's reference to this request */ globus_i_gass_transfer_request_destroy(request); globus_i_gass_transfer_unlock(); return; case GLOBUS_GASS_TRANSFER_REQUEST_PENDING: case GLOBUS_GASS_TRANSFER_REQUEST_FAILING: case GLOBUS_GASS_TRANSFER_REQUEST_FAILED: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL1: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL2: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL3: case GLOBUS_GASS_TRANSFER_REQUEST_USER_FAIL: case GLOBUS_GASS_TRANSFER_REQUEST_REFERRED: case GLOBUS_GASS_TRANSFER_REQUEST_DENIED: case GLOBUS_GASS_TRANSFER_REQUEST_DONE: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING2: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING3: case GLOBUS_GASS_TRANSFER_REQUEST_ACCEPTING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING: case GLOBUS_GASS_TRANSFER_REQUEST_FINISHING: case GLOBUS_GASS_TRANSFER_REQUEST_REFERRING: globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_PENDING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_FAILING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_FAILED); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL1); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL2); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL3); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_USER_FAIL); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_REFERRED); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_DENIED); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_DONE); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_STARTING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_STARTING2); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_STARTING3); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACCEPTING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_FINISHING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_REFERRING); goto finish; case GLOBUS_GASS_TRANSFER_REQUEST_INVALID: goto finish; } finish: globus_i_gass_transfer_unlock(); return; }
/** * Request referred. * @ingroup globus_gass_transfer_protocol * * This function notifies the GASS Transfer Library that new request * generated by a client calling one of the functions in the * "@ref globus_gass_transfer_client" section of the manual has been * referred to another URL by the server, and so processing has stopped. * * @param request * The request handle used for this request. This was created by * the user calling one of the functions in the "@ref * globus_gass_transfer_client" section of this manual. * @param url * An array of url strings containing alternate locations for this * file. The GASS transfer library is responsible for freeing this * array. It must be allocated using one of the * memory allocators defined in the Globus Common Library. * @param num_urls * The length of the @a url array. * * @see globus_gass_transfer_proto_request_ready(), * globus_gass_transfer_proto_request_denied(), * globus_gass_transfer_proto_request_referred() */ void globus_gass_transfer_proto_request_referred( globus_gass_transfer_request_t request, char ** url, globus_size_t num_urls) { globus_gass_transfer_request_struct_t * req; globus_gass_transfer_callback_t callback; void * callback_arg; globus_size_t i; globus_gass_transfer_pending_t * head; globus_i_gass_transfer_lock(); req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { goto finish; } switch(req->status) { case GLOBUS_GASS_TRANSFER_REQUEST_STARTING: req->status = GLOBUS_GASS_TRANSFER_REQUEST_REFERRED; req->referral_url = url; req->referral_count = num_urls; callback = req->callback; callback_arg = req->callback_arg; globus_i_gass_transfer_unlock(); callback(callback_arg, request); globus_i_gass_transfer_lock(); /* free up GASS's reference to the request */ globus_i_gass_transfer_request_destroy(request); break; case GLOBUS_GASS_TRANSFER_REQUEST_USER_FAIL: req->status = GLOBUS_GASS_TRANSFER_REQUEST_FAILED; req->referral_url = url; req->referral_count = num_urls; callback = req->callback; callback_arg = req->callback_arg; globus_i_gass_transfer_unlock(); callback(callback_arg, request); globus_i_gass_transfer_lock(); /* free up GASS's reference to the request */ globus_i_gass_transfer_request_destroy(request); break; case GLOBUS_GASS_TRANSFER_REQUEST_ACTING: /* request is in progress, when operation completes, * the callback queue will be drained */ req->status = GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING; req->referral_url = url; req->referral_count = num_urls; break; case GLOBUS_GASS_TRANSFER_REQUEST_PENDING: req->status = GLOBUS_GASS_TRANSFER_REQUEST_REFERRING; while(!globus_fifo_empty(&req->pending_data)) { head = globus_fifo_dequeue(&req->pending_data); /* Call back to user */ globus_i_gass_transfer_unlock(); head->callback(head->callback_arg, request, head->bytes, 0, GLOBUS_TRUE); globus_i_gass_transfer_lock(); globus_free(head); req->status = GLOBUS_GASS_TRANSFER_REQUEST_REFERRED; } /* free up references to request and proto */ req->proto->destroy(req->proto, request); /* free up the GASS's reference to this request */ globus_i_gass_transfer_request_destroy(request); break; case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING: /* user callback in progress */ req->status = GLOBUS_GASS_TRANSFER_REQUEST_REFERRING; req->referral_url = url; req->referral_count = num_urls; /* callbacks are going to occur after the current * one completes (in the operation_complete function * above) */ break; case GLOBUS_GASS_TRANSFER_REQUEST_FAILED: case GLOBUS_GASS_TRANSFER_REQUEST_REFERRED: case GLOBUS_GASS_TRANSFER_REQUEST_DENIED: case GLOBUS_GASS_TRANSFER_REQUEST_DONE: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL1: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL2: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL3: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING2: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING3: case GLOBUS_GASS_TRANSFER_REQUEST_ACCEPTING: case GLOBUS_GASS_TRANSFER_REQUEST_FAILING: case GLOBUS_GASS_TRANSFER_REQUEST_FINISHING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING: /* free urls, no state change */ goto free_urls; case GLOBUS_GASS_TRANSFER_REQUEST_REFERRING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING: globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_REFERRING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING); goto free_urls; case GLOBUS_GASS_TRANSFER_REQUEST_INVALID: goto finish; } finish: globus_i_gass_transfer_unlock(); return; free_urls: for(i = 0; i < num_urls; i++) { globus_free(url[i]); } globus_free(url); return; }
/** * Request denied. * @ingroup globus_gass_transfer_protocol * * This function notifies the GASS Transfer Library that new request * generated by a client calling one of the functions in the * "@ref globus_gass_transfer_client" section of the manual has been * denied by the server, and so cannot be processed by * the protocol module. * * @param request * The request handle used for this request. This was created by * the user calling one of the functions in the "@ref * globus_gass_transfer_client" section of this manual. * @param reason * A protocol-specific reason code. * @param message * A string containing a message describing why the request * was denied. The GASS Transfer library is responsible for * freeing this message. It must be allocated using one of the * memory allocators defined in the Globus Common Library. * * @see globus_gass_transfer_proto_request_ready(), * globus_gass_transfer_proto_request_referred() */ void globus_gass_transfer_proto_request_denied( globus_gass_transfer_request_t request, int reason, char * message) { globus_gass_transfer_request_struct_t * req; globus_gass_transfer_callback_t callback; void * callback_arg; globus_i_gass_transfer_lock(); req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { goto finish; } switch(req->status) { case GLOBUS_GASS_TRANSFER_REQUEST_STARTING: case GLOBUS_GASS_TRANSFER_REQUEST_USER_FAIL: req->status = GLOBUS_GASS_TRANSFER_REQUEST_DENIED; req->denial_reason = reason; req->denial_message = message; callback = req->callback; callback_arg = req->callback_arg; globus_i_gass_transfer_unlock(); callback(callback_arg, request); globus_i_gass_transfer_lock(); /* free up proto's and GASS's reference to the request */ globus_i_gass_transfer_request_destroy(request); break; case GLOBUS_GASS_TRANSFER_REQUEST_REFERRED: case GLOBUS_GASS_TRANSFER_REQUEST_REFERRING: case GLOBUS_GASS_TRANSFER_REQUEST_DENIED: case GLOBUS_GASS_TRANSFER_REQUEST_DONE: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING: case GLOBUS_GASS_TRANSFER_REQUEST_PENDING: case GLOBUS_GASS_TRANSFER_REQUEST_FAILED: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL1: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL2: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL3: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING2: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING3: case GLOBUS_GASS_TRANSFER_REQUEST_ACCEPTING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING: case GLOBUS_GASS_TRANSFER_REQUEST_FAILING: case GLOBUS_GASS_TRANSFER_REQUEST_FINISHING: globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_REFERRED); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_REFERRING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_DENIED); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_DONE); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_PENDING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_FAILED); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL1); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL2); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL3); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_STARTING2); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_STARTING3); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACCEPTING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_FAILING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_FINISHING); goto finish; case GLOBUS_GASS_TRANSFER_REQUEST_INVALID: goto finish; } finish: globus_i_gass_transfer_unlock(); return; }
/** * New listener request. * @ingroup globus_gass_transfer_protocol * * This function notifies the GASS Transfer Library that new request * generated by a server calling the globus_gass_transfer_register_accept() * function has begun processing in a protocol module, * and that protocol module is now ready to send or receive data to handle * this request. * * @param listener * The listener handle used to accept this request. * @param request * The request handle used for this request. This was created by * the user calling one of the functions in the "@ref * globus_gass_transfer_client" section of this manual. * @param proto * The protocol-module specific request structure. This structure * contains a set of function pointers to allow GASS to continue * to process this request. */ void globus_gass_transfer_proto_new_listener_request( globus_gass_transfer_listener_t listener, globus_gass_transfer_request_t request, globus_gass_transfer_request_proto_t * proto) { globus_gass_transfer_listener_struct_t * l; globus_gass_transfer_request_struct_t * req; globus_i_gass_transfer_lock(); l = globus_handle_table_lookup(&globus_i_gass_transfer_listener_handles, listener); if(l == GLOBUS_NULL) { globus_i_gass_transfer_unlock(); return; } req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { globus_i_gass_transfer_unlock(); return; } req->proto = proto; switch(l->status) { case GLOBUS_GASS_TRANSFER_LISTENER_ACCEPTING: l->status = GLOBUS_GASS_TRANSFER_LISTENER_STARTING; if(proto == GLOBUS_NULL) { req->status = GLOBUS_GASS_TRANSFER_REQUEST_FAILED; /* Destroy GASS's reference to this request proto */ globus_i_gass_transfer_request_destroy(request); } else { req->status = GLOBUS_GASS_TRANSFER_REQUEST_STARTING2; globus_assert(req->type != GLOBUS_GASS_TRANSFER_REQUEST_TYPE_INVALID); } /* Callback to user, regarding this request */ globus_i_gass_transfer_unlock(); req->callback(req->callback_arg, request); return; case GLOBUS_GASS_TRANSFER_LISTENER_CLOSING2: l->status = GLOBUS_GASS_TRANSFER_LISTENER_CLOSED; req->status = GLOBUS_GASS_TRANSFER_REQUEST_FAILED; /* Callback to user, regarding this request */ globus_i_gass_transfer_unlock(); req->callback(req->callback_arg, request); globus_i_gass_transfer_lock(); /* * Fail and destroy this request, since the user * has called the close function on this listener */ if(req->proto) { req->proto->fail(req->proto, request); req->proto->destroy(req->proto, request); } /* Destroy GASS's reference to this request proto */ globus_i_gass_transfer_request_destroy(request); /* Callback to user, regarding this listener */ globus_i_gass_transfer_unlock(); l->close_callback(l->close_callback_arg, listener); l->proto->destroy(l->proto, listener); globus_i_gass_transfer_lock(); /* Destroy GASS's reference to this listener */ globus_i_gass_transfer_listener_destroy(listener); globus_i_gass_transfer_listener_destroy(listener); globus_i_gass_transfer_unlock(); return; case GLOBUS_GASS_TRANSFER_LISTENER_STARTING: case GLOBUS_GASS_TRANSFER_LISTENER_INVALID: case GLOBUS_GASS_TRANSFER_LISTENER_READY: case GLOBUS_GASS_TRANSFER_LISTENER_LISTENING: case GLOBUS_GASS_TRANSFER_LISTENER_CLOSING1: case GLOBUS_GASS_TRANSFER_LISTENER_CLOSED: globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_STARTING); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_INVALID); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_READY); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_LISTENING); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_CLOSING1); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_CLOSED); } globus_i_gass_transfer_unlock(); return; }
/** * Request ready. * @ingroup globus_gass_transfer_protocol * * This function notifies the GASS Transfer Library that new request * generated by a client has begun processing in a protocol module, * and that protocol module is now ready to send or receive data to handle * this request. * * @param request * The request handle used for this request. This was created by * the user calling one of the functions in the "@ref * globus_gass_transfer_client" section of this manual. * @param proto * The protocol-module specific request structure. This structure * contains a set of function pointers to allow GASS to continue * to process this request. * * @see globus_gass_transfer_proto_request_referred(), * globus_gass_transfer_proto_request_denied() */ void globus_gass_transfer_proto_request_ready( globus_gass_transfer_request_t request, globus_gass_transfer_request_proto_t * proto) { globus_gass_transfer_request_struct_t * req; globus_gass_transfer_callback_t callback; void * callback_arg; globus_i_gass_transfer_lock(); req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { goto finish; } switch(req->status) { case GLOBUS_GASS_TRANSFER_REQUEST_STARTING3: req->status = GLOBUS_GASS_TRANSFER_REQUEST_PENDING; req->proto = proto; if(req->type == GLOBUS_GASS_TRANSFER_REQUEST_TYPE_PUT || req->type == GLOBUS_GASS_TRANSFER_REQUEST_TYPE_APPEND) { globus_i_gass_transfer_recv_dispatcher(request); } else { globus_i_gass_transfer_send_dispatcher(request); } globus_i_gass_transfer_unlock(); return; case GLOBUS_GASS_TRANSFER_REQUEST_STARTING: req->status = GLOBUS_GASS_TRANSFER_REQUEST_PENDING; req->proto = proto; callback = req->callback; callback_arg = req->callback_arg; globus_i_gass_transfer_unlock(); callback(callback_arg, request); return; case GLOBUS_GASS_TRANSFER_REQUEST_USER_FAIL: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL3: req->status = GLOBUS_GASS_TRANSFER_REQUEST_FAILED; req->proto = proto; callback = req->callback; callback_arg = req->callback_arg; globus_i_gass_transfer_unlock(); callback(callback_arg, request); globus_i_gass_transfer_lock(); /* free up references to request and proto */ req->proto->destroy(req->proto, request); /* free up GASS's reference to this request */ globus_i_gass_transfer_request_destroy(request); break; case GLOBUS_GASS_TRANSFER_REQUEST_ACTING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING: case GLOBUS_GASS_TRANSFER_REQUEST_PENDING: case GLOBUS_GASS_TRANSFER_REQUEST_FAILED: case GLOBUS_GASS_TRANSFER_REQUEST_REFERRING: case GLOBUS_GASS_TRANSFER_REQUEST_REFERRED: case GLOBUS_GASS_TRANSFER_REQUEST_DENIED: case GLOBUS_GASS_TRANSFER_REQUEST_DONE: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL1: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL2: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING2: case GLOBUS_GASS_TRANSFER_REQUEST_ACCEPTING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING: case GLOBUS_GASS_TRANSFER_REQUEST_FAILING: case GLOBUS_GASS_TRANSFER_REQUEST_FINISHING: globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_PENDING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_FAILED); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_REFERRING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_REFERRED); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_DENIED); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_DONE); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL1); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL2); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_STARTING2); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACCEPTING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_FAILING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_FINISHING); /* FALLSTHROUGH */ case GLOBUS_GASS_TRANSFER_REQUEST_INVALID: goto finish; } finish: globus_i_gass_transfer_unlock(); return; }
/** * Server listener ready. * @ingroup globus_gass_transfer_protocol * * This function notifies the GASS Transfer Library that the protocol module * has decided that a new request can be accepted on this particular listener. * It must only be called after the GASS Transfer Library has called the * @link globus_gass_transfer_listener_proto_t::listen listen function@endlink * in a #globus_gass_transfer_listener_proto_t protocol module-specific * listener structure. * * @param listener * The listener handle which is now ready for accepting a new * connection. */ void globus_gass_transfer_proto_listener_ready( globus_gass_transfer_listener_t listener) { globus_gass_transfer_listener_struct_t * l; globus_gass_transfer_listen_callback_t callback; void * callback_arg; globus_gass_transfer_listen_callback_t close_callback = GLOBUS_NULL; void * close_callback_arg; globus_i_gass_transfer_lock(); l = globus_handle_table_lookup(&globus_i_gass_transfer_listener_handles, listener); if(l == GLOBUS_NULL) { goto error_exit; } switch(l->status) { case GLOBUS_GASS_TRANSFER_LISTENER_INVALID: goto error_exit; case GLOBUS_GASS_TRANSFER_LISTENER_LISTENING: l->status = GLOBUS_GASS_TRANSFER_LISTENER_READY; callback = l->listen_callback; callback_arg = l->listen_callback_arg; globus_i_gass_transfer_unlock(); callback(callback_arg, listener); return; case GLOBUS_GASS_TRANSFER_LISTENER_CLOSING1: l->status = GLOBUS_GASS_TRANSFER_LISTENER_CLOSED; callback = l->listen_callback; callback_arg = l->listen_callback_arg; close_callback = l->close_callback; close_callback_arg = l->close_callback_arg; /* Destroy our reference to the proto */ l->proto->destroy(l->proto, listener); /* * Destroy GASS's reference * to this listener */ globus_i_gass_transfer_listener_destroy(listener); globus_i_gass_transfer_unlock(); callback(callback_arg, listener); if(close_callback) { close_callback(close_callback_arg, listener); } globus_i_gass_transfer_lock(); globus_i_gass_transfer_listener_destroy(listener); globus_i_gass_transfer_unlock(); return; case GLOBUS_GASS_TRANSFER_LISTENER_READY: case GLOBUS_GASS_TRANSFER_LISTENER_STARTING: case GLOBUS_GASS_TRANSFER_LISTENER_ACCEPTING: case GLOBUS_GASS_TRANSFER_LISTENER_CLOSING2: case GLOBUS_GASS_TRANSFER_LISTENER_CLOSED: globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_READY); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_STARTING); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_ACCEPTING); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_CLOSING2); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_CLOSED); break; } globus_i_gass_transfer_unlock(); return; error_exit: globus_i_gass_transfer_unlock(); }
static void globus_l_gass_transfer_drain_callbacks( void * arg) { globus_gass_transfer_request_t request; globus_gass_transfer_request_struct_t * req; globus_gass_transfer_callback_t callback; void * callback_arg; request = (globus_gass_transfer_request_t) arg; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { return; } if(globus_i_gass_transfer_deactivating) { callback = globus_i_gass_transfer_deactivate_callback; callback_arg = GLOBUS_NULL; } else { callback = req->fail_callback; callback_arg = req->fail_callback_arg; } /* drain queue of pending data requests */ while(!globus_fifo_empty(&req->pending_data)) { globus_gass_transfer_pending_t * pending; pending = globus_fifo_dequeue(&req->pending_data); if(!globus_i_gass_transfer_deactivating) { globus_i_gass_transfer_unlock(); pending->callback(pending->callback_arg, request, pending->bytes, 0, GLOBUS_TRUE); globus_i_gass_transfer_lock(); } globus_free(pending); } /* free up references to request and proto */ req->proto->destroy(req->proto, request); /* free up GASS's reference to this request */ globus_i_gass_transfer_request_destroy(request); if(callback) { callback(callback_arg, request); } }
/** * Receive a byte array associated with a request handle. * @ingroup globus_gass_transfer_data * * This function receives a block of data from a server or client as * part of the processing for a request. Multiple data blocks may be * registered with the GASS transfer library at once. * * When processing a server request, this function may only be used in * conjunction with "put" or "append" requests. The user must call * globus_gass_transfer_authorize() before calling this function. * * When processing a client request, this function may only be used in * conjunction with "get" requests. This function may not * be called before either the callback function has been invoked, or the * blocking globus_gass_tranfser_put() or globus_gass_transfer_append() * function has returned. * * @param request * The request handle with which this block of bytes is associated. * @param bytes * A user-supplied buffer containing the data associated with the * request. * @param max_length * The length of the @a bytes array. * @param wait_for_length * The minimum amount of data to wait for before invoking the @a * callback function. A partial byte array of at least this amount * will be returned in the callback, unless end-of-file is reached * before this amount. * @param callback * Function to call once the @a bytes array has been received. * @param user_arg * Argument to be passed to the @a callback function. * * @retval GLOBUS_SUCCESS * The @a bytes array was successfully registered with the GASS * transfer library. The @a callback function will be invoked once * it has been received. * @retval GLOBUS_GASS_TRANSFER_ERROR_NULL_POINTER * The @a bytes or @a callback parameter was NULL. * @retval GLOBUS_GASS_TRANSFER_ERROR_INVALID_USER * The @a request was invalid, or it is not one on which bytes * can be sent. * @retval GLOBUS_GASS_TRANSFER_ERROR_NOT_INITIALIZED * The callback to a non-blocking file request has not been invoked * yet, a blocking file request has not returned, or the request has * not yet been authorized. * @retval GLOBUS_GASS_TRANSFER_ERROR_REQUEST_FAILED * The @a request has failed by either the client, server, or protocol * module implementation. * @retval GLOBUS_GASS_TRANSFER_ERROR_DONE * The @a request has already been completed. */ int globus_gass_transfer_receive_bytes( globus_gass_transfer_request_t request, globus_byte_t * bytes, globus_size_t max_length, globus_size_t wait_for_length, globus_gass_transfer_bytes_callback_t callback, void * user_arg) { int rc; globus_gass_transfer_pending_t * pending; globus_gass_transfer_request_struct_t * req; globus_i_gass_transfer_lock(); /* Sanity check on passed arguments */ if(bytes == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_NULL_POINTER; goto error_exit; } if(callback == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_NULL_POINTER; goto error_exit; } req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; goto error_exit; } /* * Verify that the request is in a state that allows new data * blocks to be received */ rc = globus_l_gass_transfer_state_check(req); if(rc != GLOBUS_SUCCESS) { goto error_exit; } if(req->client_side == GLOBUS_FALSE && req->type != GLOBUS_GASS_TRANSFER_REQUEST_TYPE_PUT && req->type != GLOBUS_GASS_TRANSFER_REQUEST_TYPE_APPEND) { rc = GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; goto error_exit; } else if(req->client_side != GLOBUS_FALSE && req->type != GLOBUS_GASS_TRANSFER_REQUEST_TYPE_GET) { rc = GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; goto error_exit; } /* * Create a pending data structure, to be queued up in the request's * fifo. */ pending = (globus_gass_transfer_pending_t *) globus_malloc(sizeof(globus_gass_transfer_pending_t)); if(pending == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_MALLOC_FAILED; goto error_exit; } pending->last_data = GLOBUS_FALSE; pending->length = max_length; pending->wait_for_length = wait_for_length; pending->pending = GLOBUS_FALSE; pending->request = request; pending->bytes = bytes; pending->callback = callback; pending->callback_arg = user_arg; globus_fifo_enqueue(&req->pending_data, pending); /* * Call the recv dispatcher to (maybe) receive some more data from the * protocol module. */ globus_i_gass_transfer_recv_dispatcher(request); globus_i_gass_transfer_unlock(); return GLOBUS_SUCCESS; error_exit: globus_i_gass_transfer_unlock(); return rc; }
/** * Send a byte array associated with a request handle. * @ingroup globus_gass_transfer_data * * This function sends a block of data to a server or client as * part of the processing for a request. Multiple data blocks may be * registered with the GASS transfer library at once. * * When processing a server request, this function may only be used in * conjunction with "get" requests. The user must call * globus_gass_transfer_authorize() before calling this function. * * When processing a client request, this function may only be used in * conjunction with "put" or "append" requests. This function may not * be called before either the callback function has been invoked, or the * blocking globus_gass_tranfser_put() or globus_gass_transfer_append() * function has returned. * * @param request * The request handle with which this block of bytes is associated. * @param bytes * A user-supplied buffer containing the data associated with the * request. * @param send_length * The length of the @a bytes array. * @param last_data * A flag to indicate whether this is the final block of data * for the request. If this is true, then the @a callback * function will be delayed until the server acknowledges that * the file has been completely received. * @param callback * Function to call once the @a bytes array has been sent. * @param user_arg * Argument to be passed to the @a callback function. * * @retval GLOBUS_SUCCESS * The @a bytes array was successfully registered with the GASS * transfer library. The @a callback function will be invoked once * it has been sent. * @retval GLOBUS_GASS_TRANSFER_ERROR_NULL_POINTER * The @a bytes or @a callback parameter was NULL. * @retval GLOBUS_GASS_TRANSFER_ERROR_INVALID_USER * The @a request was invalid, or it is not one on which bytes * can be sent. * @retval GLOBUS_GASS_TRANSFER_ERROR_NOT_INITIALIZED * The callback to a non-blocking file request has not been invoked * yet, a blocking file request has not returned, or the request has * not yet been authorized. * @retval GLOBUS_GASS_TRANSFER_ERROR_REQUEST_FAILED * The @a request has failed by either the client, server, or protocol * module implementation. * @retval GLOBUS_GASS_TRANSFER_ERROR_DONE * The @a request has already been completed. */ int globus_gass_transfer_send_bytes( globus_gass_transfer_request_t request, globus_byte_t * bytes, globus_size_t send_length, globus_bool_t last_data, globus_gass_transfer_bytes_callback_t callback, void * user_arg) { int rc; globus_gass_transfer_pending_t * pending; globus_gass_transfer_request_struct_t * req; globus_i_gass_transfer_lock(); /* Sanity check on passed arguments */ if(bytes == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_NULL_POINTER; goto error_exit; } if(callback == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_NULL_POINTER; goto error_exit; } req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; goto error_exit; } else if(req->client_side == GLOBUS_FALSE && req->type != GLOBUS_GASS_TRANSFER_REQUEST_TYPE_GET) { rc = GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; goto error_exit; } else if(req->client_side != GLOBUS_FALSE && req->type != GLOBUS_GASS_TRANSFER_REQUEST_TYPE_PUT && req->type != GLOBUS_GASS_TRANSFER_REQUEST_TYPE_APPEND) { rc = GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; goto error_exit; } /* * Verify that the request is in a state that allows new data * blocks to be sent */ rc = globus_l_gass_transfer_state_check(req); if(rc != GLOBUS_SUCCESS) { goto error_exit; } /* * Verify that the sending this amount of data won't overflow the * original request size. */ rc = globus_l_gass_transfer_size_check(req, send_length); if(rc != GLOBUS_SUCCESS) { goto error_exit; } /* * Create a pending data structure, to be queued up in the request's * fifo. */ pending = (globus_gass_transfer_pending_t *) globus_malloc(sizeof(globus_gass_transfer_pending_t)); if(pending == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_MALLOC_FAILED; goto error_exit; } pending->last_data = last_data; pending->length = send_length; pending->pending = GLOBUS_FALSE; pending->request = request; pending->bytes = bytes; pending->callback = callback; pending->callback_arg = user_arg; /* * Posted length is the total amount of data which has been queued * for this request. It is used for detecting overflows. */ req->posted_length += send_length; globus_fifo_enqueue(&req->pending_data, pending); /* * Call the send dispatcher to (maybe) send some more data to the * protocol module to send over the connection. */ globus_i_gass_transfer_send_dispatcher(request); globus_i_gass_transfer_unlock(); return GLOBUS_SUCCESS; error_exit: globus_i_gass_transfer_unlock(); return rc; }