PageRenderTime 56ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 2ms

/globus_gass_transfer-7.2/library/globus_gass_transfer_http.c

#
C | 6483 lines | 5093 code | 648 blank | 742 comment | 687 complexity | de1586f4ef60c82a9264f1084549746c MD5 | raw file
Possible License(s): Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright 1999-2006 University of Chicago
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
  17. /**
  18. * @file globus_gass_transfer_http.c http/https Protocol Module Implementation
  19. *
  20. * This module implements the http and https URL schemes for the GASS transfer
  21. * library
  22. *
  23. * CVS Information:
  24. * $Source: /home/globdev/CVS/globus-packages/gass/transfer/source/library/globus_gass_transfer_http.c,v $
  25. * $Date: 2009/11/11 19:48:37 $
  26. * $Revision: 1.48 $
  27. * $Author: bester $
  28. */
  29. #endif
  30. #include "globus_i_gass_transfer.h"
  31. #include "globus_io.h"
  32. #include "globus_l_gass_transfer_http.h"
  33. #include <stdlib.h>
  34. #include <ctype.h>
  35. #include <string.h>
  36. #ifndef TARGET_ARCH_WIN32
  37. #include <strings.h>
  38. #endif
  39. #include "version.h"
  40. #ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
  41. /*
  42. #define DEBUG_GASS_TRANSFER
  43. */
  44. typedef struct
  45. {
  46. globus_gass_transfer_http_listener_proto_t * l_proto;
  47. globus_gass_transfer_request_t request;
  48. }
  49. globus_l_gass_transfer_failed_kickout_closure_t;
  50. #if defined(DEBUG_GASS_TRANSFER)
  51. static char * globus_l_gass_transfer_http_debug_level="";
  52. /* Debug Levels */
  53. /* 1: Major entry points to the library are displayed */
  54. /* 2: Calls into the gass transfer proto API are displayed */
  55. /* 3: Callbacks are displayed */
  56. /* 4: Callback Registration is displayed */
  57. /* 5: Error returns from lower-level calls */
  58. /* 6: Protocol dumps */
  59. /* 9: Thread safety */
  60. #define debug_printf(level,fmt) \
  61. if(strchr(globus_l_gass_transfer_http_debug_level, (#level)[0])) \
  62. {\
  63. printf fmt;\
  64. }
  65. #undef globus_l_gass_transfer_http_lock
  66. #undef globus_l_gass_transfer_http_unlock
  67. static int globus_l_gass_lock_line=0;
  68. static int globus_l_gass_lock_tmp=0;
  69. #define MYNAME(x) static char * myname=#x
  70. #define globus_l_gass_transfer_http_lock() \
  71. printf(strchr(globus_l_gass_transfer_http_debug_level,'9') ? "Thread [%d] acquiring mutex at %s:%d\n" : "", \
  72. (int) globus_thread_self(), \
  73. __FILE__, \
  74. __LINE__), \
  75. fflush(stdout), \
  76. globus_l_gass_lock_tmp = \
  77. globus_mutex_lock(&globus_l_gass_transfer_http_mutex), \
  78. globus_l_gass_lock_line=__LINE__, \
  79. globus_l_gass_lock_tmp
  80. #define globus_l_gass_transfer_http_unlock() \
  81. printf(strchr(globus_l_gass_transfer_http_debug_level, '9') ? "Thread [%d] releasing mutex at %s:%d\n" : "", \
  82. (int) globus_thread_self(), \
  83. __FILE__, \
  84. __LINE__), \
  85. fflush(stdout), \
  86. globus_l_gass_lock_line = 0, \
  87. globus_mutex_unlock(&globus_l_gass_transfer_http_mutex)
  88. #else
  89. #define debug_printf(level, fmt)
  90. #define MYNAME(x)
  91. #endif
  92. static
  93. void
  94. globus_l_gass_transfer_http_accept_failed_kickout(
  95. void * arg);
  96. static volatile int globus_l_gass_transfer_http_closing;
  97. #if !defined(GLOBUS_GASS_TRANSFER_HTTP_PARSER_TEST)
  98. int
  99. globus_l_gass_transfer_http_activate(void)
  100. {
  101. OM_uint32 maj_stat;
  102. OM_uint32 min_stat;
  103. gss_name_t name;
  104. gss_cred_id_t globus_l_gass_transfer_http_credential =
  105. GSS_C_NO_CREDENTIAL;
  106. gss_buffer_desc name_buffer;
  107. MYNAME(globus_l_gass_transfer_http_activate);
  108. globus_l_gass_transfer_http_closing = 0;
  109. name_buffer.value = GLOBUS_NULL;
  110. name_buffer.length = 0;
  111. # if defined(DEBUG_GASS_TRANSFER)
  112. {
  113. globus_l_gass_transfer_http_debug_level =
  114. globus_module_getenv("GLOBUS_GASS_TRANSFER_HTTP_DEBUG_LEVEL");
  115. if(globus_l_gass_transfer_http_debug_level == GLOBUS_NULL)
  116. {
  117. globus_l_gass_transfer_http_debug_level = "";
  118. }
  119. }
  120. # endif
  121. debug_printf(1, (_GTSL("Entering %s()\n"),myname));
  122. globus_module_activate(GLOBUS_COMMON_MODULE);
  123. globus_module_activate(GLOBUS_GSI_GSS_ASSIST_MODULE);
  124. globus_module_activate(GLOBUS_IO_MODULE);
  125. globus_mutex_init(&globus_l_gass_transfer_http_mutex,
  126. GLOBUS_NULL);
  127. globus_cond_init(&globus_l_gass_transfer_http_cond,
  128. GLOBUS_NULL);
  129. maj_stat = globus_gss_assist_acquire_cred(
  130. &min_stat,
  131. GSS_C_BOTH,
  132. &globus_l_gass_transfer_http_credential);
  133. if (maj_stat != GSS_S_COMPLETE)
  134. {
  135. goto error_exit;
  136. }
  137. maj_stat = gss_inquire_cred(
  138. &min_stat,
  139. globus_l_gass_transfer_http_credential,
  140. &name,
  141. GLOBUS_NULL,
  142. GLOBUS_NULL,
  143. GLOBUS_NULL);
  144. if (maj_stat != GSS_S_COMPLETE)
  145. {
  146. goto error_exit;
  147. }
  148. maj_stat = gss_display_name(
  149. &min_stat,
  150. name,
  151. &name_buffer,
  152. GLOBUS_NULL);
  153. if (maj_stat != GSS_S_COMPLETE)
  154. {
  155. goto error_exit;
  156. }
  157. maj_stat = gss_release_name(
  158. &min_stat,
  159. &name);
  160. if (maj_stat != GSS_S_COMPLETE)
  161. {
  162. goto error_exit;
  163. }
  164. globus_l_gass_transfer_http_subject_name = name_buffer.value;
  165. if (globus_l_gass_transfer_http_credential != GSS_C_NO_CREDENTIAL)
  166. {
  167. gss_release_cred(&min_stat, &globus_l_gass_transfer_http_credential);
  168. }
  169. debug_printf(1, (_GTSL("Exiting %s()\n"),myname));
  170. return GLOBUS_SUCCESS;
  171. error_exit:
  172. if (globus_l_gass_transfer_http_credential != GSS_C_NO_CREDENTIAL)
  173. {
  174. gss_release_cred(&min_stat, &globus_l_gass_transfer_http_credential);
  175. }
  176. debug_printf(1, (_GTSL("Exiting %s()\n"),myname));
  177. return GLOBUS_FAILURE;
  178. }
  179. int
  180. globus_l_gass_transfer_http_deactivate(void)
  181. {
  182. MYNAME(globus_l_gass_transfer_http_deactivate);
  183. debug_printf(1, (_GTSL("Entering %s()\n"),myname));
  184. globus_l_gass_transfer_http_lock();
  185. while(globus_l_gass_transfer_http_closing > 0)
  186. {
  187. globus_l_gass_transfer_http_wait();
  188. }
  189. globus_l_gass_transfer_http_unlock();
  190. globus_module_deactivate(GLOBUS_IO_MODULE);
  191. globus_module_deactivate(GLOBUS_GSI_GSS_ASSIST_MODULE);
  192. globus_mutex_destroy(&globus_l_gass_transfer_http_mutex);
  193. globus_cond_destroy(&globus_l_gass_transfer_http_cond);
  194. globus_free(globus_l_gass_transfer_http_subject_name);
  195. globus_module_deactivate(GLOBUS_COMMON_MODULE);
  196. debug_printf(1, (_GTSL("Exiting %s()\n"),myname));
  197. return GLOBUS_SUCCESS;
  198. }
  199. globus_module_descriptor_t globus_i_gass_transfer_http_module =
  200. {
  201. "globus_i_gass_transfer_http",
  202. globus_l_gass_transfer_http_activate,
  203. globus_l_gass_transfer_http_deactivate,
  204. GLOBUS_NULL,
  205. GLOBUS_NULL,
  206. &local_version
  207. };
  208. /* Protocol Descriptor, which is registered with the GASS system */
  209. globus_gass_transfer_proto_descriptor_t
  210. globus_i_gass_transfer_http_descriptor =
  211. {
  212. "http",
  213. /* client-side support */
  214. globus_l_gass_transfer_http_new_requestattr,
  215. globus_l_gass_transfer_http_new_request,
  216. /* server-side support */
  217. globus_l_gass_transfer_http_new_listenerattr /* new_listenerattr */,
  218. globus_l_gass_transfer_http_new_listener /* new_listener */
  219. };
  220. globus_gass_transfer_proto_descriptor_t
  221. globus_i_gass_transfer_https_descriptor =
  222. {
  223. "https",
  224. /* client-side support */
  225. globus_l_gass_transfer_http_new_requestattr,
  226. globus_l_gass_transfer_http_new_request,
  227. /* server-side support */
  228. globus_l_gass_transfer_http_new_listenerattr /* new_listenerattr */,
  229. globus_l_gass_transfer_http_new_listener /* new_listener */
  230. };
  231. /*
  232. * Function: globus_l_gass_transfer_http_send()
  233. *
  234. * Description: Send a byte array to an HTTP server
  235. *
  236. * Parameters:
  237. *
  238. * Returns:
  239. */
  240. static
  241. void
  242. globus_l_gass_transfer_http_send(
  243. globus_gass_transfer_request_proto_t * proto,
  244. globus_gass_transfer_request_t request,
  245. globus_byte_t * buffer,
  246. globus_size_t buffer_length,
  247. globus_bool_t last_data)
  248. {
  249. globus_result_t result;
  250. globus_gass_transfer_http_request_proto_t * new_proto;
  251. globus_reltime_t delay_time;
  252. MYNAME(globus_l_gass_transfer_http_send);
  253. debug_printf(1, (_GTSL("Entering %s()\n"),myname));
  254. globus_l_gass_transfer_http_lock();
  255. new_proto = (globus_gass_transfer_http_request_proto_t *) proto;
  256. new_proto->last_data = last_data;
  257. /* We can only process a send if the proto is in the "idle" state */
  258. globus_assert(new_proto->state == GLOBUS_GASS_TRANSFER_HTTP_STATE_IDLE);
  259. /* state change to "pending" */
  260. new_proto->state = GLOBUS_GASS_TRANSFER_HTTP_STATE_PENDING;
  261. /* Update the buffers to point to those supplied by the user */
  262. new_proto->user_buffer = buffer;
  263. new_proto->user_buflen = buffer_length;
  264. /* If a a failure occurred, callback with the failure bit set,
  265. * and close the handle
  266. */
  267. if(new_proto->failure_occurred)
  268. {
  269. goto fail_exit;
  270. }
  271. /* Register the send of the data */
  272. if(new_proto->chunked)
  273. {
  274. globus_size_t num_iovecs;
  275. /* send chunk header and footer as an iovec array */
  276. sprintf((char *) new_proto->iov[0].iov_base,
  277. "%lx%s",
  278. (long) new_proto->user_buflen,
  279. CRLF);
  280. new_proto->iov[0].iov_len = strlen((char *) new_proto->iov[0].iov_base);
  281. new_proto->iov[1].iov_base = (void *) new_proto->user_buffer;
  282. new_proto->iov[1].iov_len = new_proto->user_buflen;
  283. new_proto->iov[2].iov_base = CRLF;
  284. new_proto->iov[2].iov_len = 2;
  285. if(last_data && new_proto->user_buflen != 0)
  286. {
  287. /* last data, need to append a zero-length chunk to
  288. * indicate this
  289. */
  290. num_iovecs = 4;
  291. }
  292. else if(last_data && new_proto->user_buflen == 0)
  293. {
  294. /* last data, with a zero-length chunk from the user */
  295. new_proto->iov[1].iov_base = CRLF;
  296. new_proto->iov[1].iov_len = 2;
  297. num_iovecs = 2;
  298. }
  299. else
  300. {
  301. /* normal chunk */
  302. num_iovecs = 3;
  303. }
  304. debug_printf(4, (_GTSL("%s(): Registering writev\n"), myname));
  305. result = globus_io_register_writev(
  306. &new_proto->handle,
  307. new_proto->iov,
  308. num_iovecs /* 3 iovecs header, body, final CRLF */,
  309. globus_l_gass_transfer_http_writev_callback,
  310. new_proto);
  311. }
  312. else
  313. {
  314. /* send data raw */
  315. debug_printf(4, (_GTSL("%s(): Registering writev\n"), myname));
  316. result = globus_io_register_write(
  317. &new_proto->handle,
  318. new_proto->user_buffer,
  319. new_proto->user_buflen,
  320. globus_l_gass_transfer_http_write_callback,
  321. new_proto);
  322. }
  323. if(result == GLOBUS_SUCCESS)
  324. {
  325. /*
  326. * Registration succeeded. Callback to GASS occurs when I/O
  327. * completes.
  328. */
  329. globus_l_gass_transfer_http_unlock();
  330. debug_printf(1, (_GTSL("exiting %s()\n"),myname));
  331. return;
  332. }
  333. fail_exit:
  334. /* Registration failed, close up handle and signal failure to GASS */
  335. result = globus_l_gass_transfer_http_register_close(new_proto);
  336. if (result != GLOBUS_SUCCESS)
  337. {
  338. globus_l_gass_transfer_http_close(new_proto);
  339. }
  340. GlobusTimeReltimeSet(delay_time, 0, 0);
  341. debug_printf(4, (_GTSL("%s(): Registering oneshot\n"), myname));
  342. globus_callback_register_oneshot(
  343. GLOBUS_NULL,
  344. &delay_time,
  345. globus_l_gass_transfer_http_callback_send_callback,
  346. (void *) new_proto);
  347. globus_l_gass_transfer_http_unlock();
  348. debug_printf(1, (_GTSL("exiting %s()\n"),myname));
  349. }
  350. /* globus_l_gass_transfer_http_send() */
  351. /*
  352. * Function: globus_l_gass_transfer_http_receive()
  353. *
  354. * Description: Schedule the next block of data from the http server
  355. * to end up in the provided byte array
  356. *
  357. * Parameters:
  358. *
  359. * Returns:
  360. */
  361. static
  362. void
  363. globus_l_gass_transfer_http_receive(
  364. globus_gass_transfer_request_proto_t * proto,
  365. globus_gass_transfer_request_t request,
  366. globus_byte_t * buffer,
  367. globus_size_t buffer_length,
  368. globus_size_t wait_for_length)
  369. {
  370. globus_gass_transfer_http_request_proto_t * new_proto;
  371. globus_reltime_t delay_time;
  372. MYNAME(globus_l_gass_transfer_http_receive);
  373. debug_printf(1, (_GTSL("Entering %s()\n"),myname));
  374. globus_l_gass_transfer_http_lock();
  375. new_proto = (globus_gass_transfer_http_request_proto_t *) proto;
  376. /* We can only process a receive if the proto is in the "idle" state */
  377. globus_assert(new_proto->state == GLOBUS_GASS_TRANSFER_HTTP_STATE_IDLE);
  378. /* state change to "pending" */
  379. new_proto->state = GLOBUS_GASS_TRANSFER_HTTP_STATE_PENDING;
  380. /* Update the buffers to point to those supplied by the user */
  381. new_proto->user_buffer = buffer;
  382. new_proto->user_buflen = buffer_length;
  383. new_proto->user_offset = 0;
  384. new_proto->user_waitlen = wait_for_length;
  385. new_proto->oneshot_registered = GLOBUS_TRUE;
  386. GlobusTimeReltimeSet(delay_time, 0, 0);
  387. debug_printf(4, (_GTSL("%s(): Registering oneshot\n"), myname));
  388. globus_callback_register_oneshot(
  389. GLOBUS_NULL,
  390. &delay_time,
  391. globus_l_gass_transfer_http_callback_read_buffered_callback,
  392. (void *) new_proto);
  393. globus_l_gass_transfer_http_unlock();
  394. debug_printf(1, (_GTSL("exiting %s()\n"),myname));
  395. }
  396. /* globus_l_gass_transfer_http_receive() */
  397. /*
  398. * Function: globus_l_gass_transfer_http_fail()
  399. *
  400. * Description: Cause the given request to fail for client-caused reasons
  401. *
  402. * Parameters:
  403. *
  404. * Returns:
  405. */
  406. static
  407. void
  408. globus_l_gass_transfer_http_fail(
  409. globus_gass_transfer_request_proto_t * proto,
  410. globus_gass_transfer_request_t request)
  411. {
  412. globus_gass_transfer_http_request_proto_t * new_proto;
  413. globus_bool_t signalled;
  414. globus_result_t result;
  415. MYNAME(globus_l_gass_transfer_http_fail);
  416. debug_printf(1, (_GTSL("entering %s()\n"),myname));
  417. new_proto = (globus_gass_transfer_http_request_proto_t *) proto;
  418. globus_l_gass_transfer_http_lock();
  419. signalled = GLOBUS_FALSE;
  420. while(!signalled)
  421. {
  422. switch(new_proto->state)
  423. {
  424. case GLOBUS_GASS_TRANSFER_HTTP_STATE_PENDING:
  425. if(new_proto->oneshot_registered == GLOBUS_TRUE)
  426. {
  427. new_proto->failure_occurred = GLOBUS_TRUE;
  428. signalled = GLOBUS_TRUE;
  429. break;
  430. }
  431. else if(new_proto->oneshot_active)
  432. {
  433. new_proto->failure_occurred = GLOBUS_TRUE;
  434. while(new_proto->state ==
  435. GLOBUS_GASS_TRANSFER_HTTP_STATE_PENDING)
  436. {
  437. globus_l_gass_transfer_http_wait();
  438. }
  439. break;
  440. }
  441. case GLOBUS_GASS_TRANSFER_HTTP_STATE_CONNECTING:
  442. case GLOBUS_GASS_TRANSFER_HTTP_STATE_IDLE:
  443. /* We will transition to the closing state, signalling the failure,
  444. * and registering the close (which will transition us to the
  445. * done state).
  446. */
  447. signalled = GLOBUS_TRUE;
  448. new_proto->failure_occurred = GLOBUS_TRUE;
  449. result = globus_l_gass_transfer_http_register_close(new_proto);
  450. if (result != GLOBUS_SUCCESS)
  451. {
  452. globus_l_gass_transfer_http_close(new_proto);
  453. }
  454. break;
  455. case GLOBUS_GASS_TRANSFER_HTTP_STATE_CLOSING:
  456. case GLOBUS_GASS_TRANSFER_HTTP_STATE_DONE:
  457. case GLOBUS_GASS_TRANSFER_HTTP_STATE_REQUESTING:
  458. case GLOBUS_GASS_TRANSFER_HTTP_STATE_RESPONDING:
  459. case GLOBUS_GASS_TRANSFER_HTTP_STATE_REFERRED:
  460. case GLOBUS_GASS_TRANSFER_HTTP_STATE_DENIED:
  461. signalled = GLOBUS_TRUE;
  462. new_proto->failure_occurred = GLOBUS_TRUE;
  463. break;
  464. }
  465. }
  466. globus_l_gass_transfer_http_unlock();
  467. debug_printf(1, (_GTSL("Exiting %s()\n"),myname));
  468. }
  469. /* globus_l_gass_transfer_http_fail() */
  470. static
  471. void
  472. globus_l_gass_transfer_http_write_callback(
  473. void * callback_arg,
  474. globus_io_handle_t * handle,
  475. globus_result_t result,
  476. globus_byte_t * buf,
  477. globus_size_t nbytes)
  478. {
  479. globus_gass_transfer_http_request_proto_t * proto;
  480. MYNAME(globus_l_gass_transfer_http_write_callback);
  481. debug_printf(3, (_GTSL("Entering %s()\n"),myname));
  482. proto = (globus_gass_transfer_http_request_proto_t *) callback_arg;
  483. globus_l_gass_transfer_http_lock();
  484. if(result != GLOBUS_SUCCESS ||
  485. proto->failure_occurred ||
  486. proto->parse_error)
  487. {
  488. proto->last_data = GLOBUS_TRUE;
  489. }
  490. if(proto->last_data)
  491. {
  492. proto->user_offset = nbytes;
  493. if((proto->type == GLOBUS_GASS_TRANSFER_REQUEST_TYPE_PUT ||
  494. proto->type == GLOBUS_GASS_TRANSFER_REQUEST_TYPE_APPEND) &&
  495. (!proto->failure_occurred && !proto->parse_error))
  496. {
  497. if(proto->got_response)
  498. {
  499. globus_byte_t * buffer;
  500. globus_size_t offset;
  501. globus_gass_transfer_request_t request = proto->request;
  502. int failed = proto->failure_occurred;
  503. proto->failure_occurred = GLOBUS_TRUE;
  504. buffer = proto->user_buffer;
  505. offset = proto->user_offset;
  506. result = globus_l_gass_transfer_http_register_close(proto);
  507. if (result != GLOBUS_SUCCESS)
  508. {
  509. globus_l_gass_transfer_http_close(proto);
  510. }
  511. globus_l_gass_transfer_http_unlock();
  512. globus_gass_transfer_proto_send_complete(request,
  513. buffer,
  514. offset,
  515. failed,
  516. GLOBUS_TRUE);
  517. debug_printf(3, (_GTSL("Exiting %s()\n"),myname));
  518. return;
  519. }
  520. else
  521. {
  522. /* the callback to read the response is registered at
  523. * the beginning of the send, so we do nothing here,
  524. * and wait for the response
  525. */
  526. proto->waiting_for_response = GLOBUS_TRUE;
  527. globus_l_gass_transfer_http_unlock();
  528. debug_printf(3, (_GTSL("Exiting %s()\n"),myname));
  529. return;
  530. }
  531. }
  532. else
  533. {
  534. globus_gass_transfer_request_t request;
  535. globus_byte_t * buf;
  536. globus_size_t nbytes_sent;
  537. globus_bool_t fail;
  538. request = proto->request;
  539. buf = proto->user_buffer;
  540. nbytes_sent = proto->user_offset;
  541. fail = proto->failure_occurred;
  542. /* need to register the close, and callback to the user */
  543. result = globus_l_gass_transfer_http_register_close(proto);
  544. if (result != GLOBUS_SUCCESS)
  545. {
  546. globus_l_gass_transfer_http_close(proto);
  547. }
  548. globus_l_gass_transfer_http_unlock();
  549. globus_gass_transfer_proto_send_complete(
  550. request,
  551. buf,
  552. nbytes_sent,
  553. fail,
  554. GLOBUS_TRUE);
  555. debug_printf(3, (_GTSL("Exiting %s()\n"),myname));
  556. return;
  557. }
  558. }
  559. else
  560. {
  561. globus_gass_transfer_request_t request;
  562. globus_byte_t * buf;
  563. globus_bool_t fail;
  564. globus_bool_t last_data;
  565. proto->state = GLOBUS_GASS_TRANSFER_HTTP_STATE_IDLE;
  566. request = proto->request;
  567. buf = proto->user_buffer;
  568. fail = proto->failure_occurred;
  569. last_data = proto->last_data;
  570. globus_l_gass_transfer_http_unlock();
  571. globus_gass_transfer_proto_send_complete(request,
  572. buf,
  573. nbytes,
  574. fail,
  575. last_data);
  576. }
  577. debug_printf(3, (_GTSL("Exiting %s()\n"),myname));
  578. return;
  579. }
  580. /* globus_l_gass_transfer_http_write_callback() */
  581. static
  582. void
  583. globus_l_gass_transfer_http_writev_callback(
  584. void * callback_arg,
  585. globus_io_handle_t * handle,
  586. globus_result_t result,
  587. struct iovec * iov,
  588. globus_size_t iovcnt,
  589. globus_size_t nbytes)
  590. {
  591. globus_gass_transfer_http_request_proto_t * proto;
  592. MYNAME(globus_l_gass_transfer_http_writev_callback);
  593. debug_printf(3, (_GTSL("Entering %s()\n"),myname));
  594. proto = (globus_gass_transfer_http_request_proto_t *) callback_arg;
  595. globus_l_gass_transfer_http_lock();
  596. if(result != GLOBUS_SUCCESS ||
  597. proto->failure_occurred ||
  598. proto->parse_error)
  599. {
  600. proto->last_data = GLOBUS_TRUE;
  601. }
  602. if(proto->last_data)
  603. {
  604. proto->user_offset = nbytes - iov[0].iov_len - iov[2].iov_len;
  605. if((proto->type == GLOBUS_GASS_TRANSFER_REQUEST_TYPE_PUT ||
  606. proto->type == GLOBUS_GASS_TRANSFER_REQUEST_TYPE_APPEND) &&
  607. (!proto->failure_occurred && !proto->parse_error))
  608. {
  609. if(proto->got_response)
  610. {
  611. globus_byte_t * buffer;
  612. globus_size_t offset;
  613. int failed = proto->failure_occurred;
  614. globus_gass_transfer_request_t request = proto->request;
  615. buffer = proto->user_buffer;
  616. offset = proto->user_offset;
  617. result = globus_l_gass_transfer_http_register_close(proto);
  618. if (result != GLOBUS_SUCCESS)
  619. {
  620. globus_l_gass_transfer_http_close(proto);
  621. }
  622. globus_l_gass_transfer_http_unlock();
  623. globus_gass_transfer_proto_send_complete(request,
  624. buffer,
  625. offset,
  626. failed,
  627. GLOBUS_TRUE);
  628. debug_printf(3, (_GTSL("Exiting %s()\n"),myname));
  629. return;
  630. }
  631. else
  632. {
  633. /* the callback to read the response is registered at
  634. * the beginning of the send, so we do nothing here,
  635. * and wait for the response
  636. */
  637. proto->waiting_for_response = GLOBUS_TRUE;
  638. globus_l_gass_transfer_http_unlock();
  639. debug_printf(3, (_GTSL("Exiting %s()\n"),myname));
  640. return;
  641. }
  642. }
  643. else
  644. {
  645. globus_gass_transfer_request_t request;
  646. globus_byte_t *buf;
  647. globus_size_t nbytes_sent;
  648. globus_bool_t fail;
  649. request = proto->request;
  650. buf = proto->user_buffer;
  651. nbytes_sent = proto->user_offset;
  652. fail = proto->failure_occurred;
  653. /* need to register the close, and callback to the user */
  654. result = globus_l_gass_transfer_http_register_close(proto);
  655. if (result != GLOBUS_SUCCESS)
  656. {
  657. globus_l_gass_transfer_http_close(proto);
  658. }
  659. globus_l_gass_transfer_http_unlock();
  660. globus_gass_transfer_proto_send_complete(
  661. request,
  662. buf,
  663. nbytes_sent,
  664. fail,
  665. GLOBUS_TRUE);
  666. debug_printf(3, (_GTSL("Exiting %s()\n"),myname));
  667. return;
  668. }
  669. }
  670. else
  671. {
  672. globus_gass_transfer_request_t request;
  673. globus_byte_t *buf;
  674. globus_size_t nbytes_sent;
  675. globus_bool_t fail;
  676. request = proto->request;
  677. buf = proto->user_buffer;
  678. nbytes_sent = nbytes - iov[0].iov_len - iov[2].iov_len,
  679. fail = proto->failure_occurred;
  680. proto->state = GLOBUS_GASS_TRANSFER_HTTP_STATE_IDLE;
  681. globus_l_gass_transfer_http_unlock();
  682. globus_gass_transfer_proto_send_complete(request,
  683. buf,
  684. nbytes_sent,
  685. fail,
  686. GLOBUS_FALSE);
  687. debug_printf(3, (_GTSL("Exiting %s()\n"),myname));
  688. return;
  689. }
  690. }
  691. /* globus_l_gass_transfer_http_writev_callback() */
  692. /*
  693. * Function: globus_l_gass_transfer_http_read_callack()
  694. *
  695. * Description: Callback when the read of from the connection to the active
  696. * buffer has completed or failed.
  697. *
  698. * Parameters:
  699. *
  700. * Returns:
  701. */
  702. static
  703. void
  704. globus_l_gass_transfer_http_read_callback(
  705. void * callback_arg,
  706. globus_io_handle_t * handle,
  707. globus_result_t result,
  708. globus_byte_t * buf,
  709. globus_size_t nbytes)
  710. {
  711. globus_object_t * err = GLOBUS_NULL;
  712. globus_gass_transfer_http_request_proto_t * proto;
  713. globus_gass_transfer_request_t request;
  714. globus_bool_t last_data = GLOBUS_FALSE;
  715. globus_bool_t failure = GLOBUS_FALSE;
  716. globus_size_t offset = 0;
  717. MYNAME(globus_l_gass_transfer_http_read_callback);
  718. debug_printf(3, (_GTSL("Entering %s()\n"),myname));
  719. proto = (globus_gass_transfer_http_request_proto_t *) callback_arg;
  720. if(result != GLOBUS_SUCCESS)
  721. {
  722. char * tmpstr;
  723. err = globus_error_get(result);
  724. tmpstr = globus_object_printable_to_string(err);
  725. debug_printf(5, (_GTSL("%s(): Error: %s\n"), myname, tmpstr));
  726. globus_libc_free(tmpstr);
  727. }
  728. globus_l_gass_transfer_http_lock();
  729. proto->user_offset += nbytes;
  730. proto->handled += nbytes;
  731. if(nbytes > proto->user_waitlen)
  732. {
  733. proto->user_waitlen = 0;
  734. }
  735. else
  736. {
  737. proto->user_waitlen -= nbytes;
  738. }
  739. if(proto->chunked)
  740. {
  741. proto->chunk_left -= nbytes;
  742. }
  743. if(result != GLOBUS_SUCCESS &&
  744. globus_io_eof(err))
  745. {
  746. proto->eof_read = GLOBUS_TRUE;
  747. }
  748. else if(result != GLOBUS_SUCCESS ||
  749. proto->failure_occurred ||
  750. proto->parse_error)
  751. {
  752. proto->recv_state = GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_ERROR;
  753. }
  754. if(proto->recv_state == GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_UNTIL_EOF &&
  755. proto->eof_read == GLOBUS_TRUE)
  756. {
  757. proto->recv_state = GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_EOF;
  758. }
  759. else if(proto->recv_state ==
  760. GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_UNTIL_LENGTH &&
  761. proto->handled == proto->length)
  762. {
  763. proto->recv_state = GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_EOF;
  764. }
  765. else if(proto->recv_state ==
  766. GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_UNTIL_LENGTH &&
  767. proto->eof_read == GLOBUS_TRUE &&
  768. proto->handled < proto->length)
  769. {
  770. proto->recv_state = GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_ERROR;
  771. }
  772. else if(nbytes==0 && proto->eof_read)
  773. {
  774. proto->failure_occurred = GLOBUS_TRUE;
  775. proto->recv_state = GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_ERROR;
  776. }
  777. if((proto->type == GLOBUS_GASS_TRANSFER_REQUEST_TYPE_PUT ||
  778. proto->type == GLOBUS_GASS_TRANSFER_REQUEST_TYPE_APPEND) &&
  779. proto->recv_state == GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_EOF)
  780. {
  781. char * response;
  782. globus_size_t response_len=0;
  783. globus_size_t offset;
  784. response_len += 1;
  785. response_len += strlen(GLOBUS_L_GENERIC_RESPONSE);
  786. response_len += 3;
  787. response_len += strlen(GLOBUS_L_OK);
  788. response_len += 2;
  789. response = globus_malloc(response_len);
  790. proto->state = GLOBUS_GASS_TRANSFER_HTTP_STATE_RESPONDING;
  791. offset = sprintf(response,
  792. GLOBUS_L_GENERIC_RESPONSE,
  793. 0,
  794. 200,
  795. GLOBUS_L_OK);
  796. offset += sprintf(response + offset,
  797. CRLF);
  798. debug_printf(4,(_GTSL("%s(): Registering write\n"),myname));
  799. globus_io_register_write(&proto->handle,
  800. (globus_byte_t *) response,
  801. strlen(response),
  802. globus_l_gass_transfer_http_write_response,
  803. proto);
  804. }
  805. /* Register the socket for closing if we're done reading from it */
  806. else if(proto->recv_state == GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_EOF ||
  807. proto->recv_state == GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_ERROR)
  808. {
  809. failure = proto->failure_occurred;
  810. buf = proto->user_buffer;
  811. offset = proto->user_offset;
  812. request = proto->request;
  813. last_data = GLOBUS_TRUE;
  814. if(proto->state != GLOBUS_GASS_TRANSFER_HTTP_STATE_CLOSING)
  815. {
  816. result = globus_l_gass_transfer_http_register_close(proto);
  817. if (result != GLOBUS_SUCCESS)
  818. {
  819. globus_l_gass_transfer_http_close(proto);
  820. }
  821. }
  822. globus_l_gass_transfer_http_unlock();
  823. debug_printf(2, (_GTSL("calling globus_gass_transfer_proto_receive_complete()")));
  824. globus_gass_transfer_proto_receive_complete(request,
  825. buf,
  826. offset,
  827. failure,
  828. last_data);
  829. goto out;
  830. }
  831. if(proto->user_waitlen == 0 ||
  832. proto->recv_state == GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_EOF ||
  833. proto->recv_state == GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_ERROR)
  834. {
  835. /*
  836. * Received the required minimum of data from connection, an
  837. * error, or the end-of file, signal this to GASS
  838. */
  839. if(proto->state == GLOBUS_GASS_TRANSFER_HTTP_STATE_PENDING)
  840. {
  841. proto->state = GLOBUS_GASS_TRANSFER_HTTP_STATE_IDLE;
  842. }
  843. if(proto->recv_state == GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_EOF ||
  844. proto->recv_state == GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_ERROR)
  845. {
  846. last_data = GLOBUS_TRUE;
  847. }
  848. failure = proto->failure_occurred;
  849. buf = proto->user_buffer;
  850. offset = proto->user_offset;
  851. request = proto->request;
  852. globus_l_gass_transfer_http_unlock();
  853. debug_printf(2, (_GTSL("calling globus_gass_transfer_proto_receive_complete()")));
  854. globus_gass_transfer_proto_receive_complete(request,
  855. buf,
  856. offset,
  857. failure,
  858. last_data);
  859. }
  860. else
  861. {
  862. result = globus_l_gass_transfer_http_register_read(proto);
  863. globus_l_gass_transfer_http_unlock();
  864. }
  865. out:
  866. if(err)
  867. {
  868. globus_object_free(err);
  869. }
  870. debug_printf(3, (_GTSL("Exiting %s()\n"),myname));
  871. return;
  872. }
  873. /* globus_l_gass_transfer_http_read_callback() */
  874. /*
  875. * Function: globus_l_gass_transfer_http_read_buffered_callack()
  876. *
  877. * Description: Callback when the read of from the http to the
  878. * response buffer has completed or failed.
  879. *
  880. * Parameters:
  881. *
  882. * Returns:
  883. */
  884. static
  885. void
  886. globus_l_gass_transfer_http_read_buffered_callback(
  887. void * callback_arg,
  888. globus_io_handle_t * handle,
  889. globus_result_t result,
  890. globus_byte_t * buf,
  891. globus_size_t nbytes)
  892. {
  893. globus_object_t * err = GLOBUS_NULL;
  894. globus_gass_transfer_http_request_proto_t * proto;
  895. MYNAME(globus_l_gass_transfer_http_read_buffered_callback);
  896. debug_printf(3, (_GTSL("Entering %s()\n"),myname));
  897. proto = (globus_gass_transfer_http_request_proto_t *) callback_arg;
  898. if(result != GLOBUS_SUCCESS)
  899. {
  900. char * tmpstr;
  901. err = globus_error_get(result);
  902. tmpstr = globus_object_printable_to_string(err);
  903. debug_printf(5, (_GTSL("%s(): %s\n"), myname, tmpstr));
  904. globus_libc_free(tmpstr);
  905. }
  906. globus_l_gass_transfer_http_lock();
  907. proto->response_offset += nbytes;
  908. if(result != GLOBUS_SUCCESS &&
  909. globus_io_eof(err))
  910. {
  911. proto->eof_read = GLOBUS_TRUE;
  912. }
  913. else if(result != GLOBUS_SUCCESS)
  914. {
  915. proto->recv_state = GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_ERROR;
  916. }
  917. /*
  918. * Copy the document from the response buffer to the user-supplied
  919. * buffer, translating end-of-line if necessary, and handling any
  920. * chunk header/footer information
  921. */
  922. globus_l_gass_transfer_http_handle_chunk(proto);
  923. if(proto->failure_occurred)
  924. {
  925. proto->recv_state = GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_ERROR;
  926. }
  927. /* successful read for server, send response */
  928. if((proto->type == GLOBUS_GASS_TRANSFER_REQUEST_TYPE_PUT ||
  929. proto->type == GLOBUS_GASS_TRANSFER_REQUEST_TYPE_APPEND) &&
  930. proto->recv_state == GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_EOF &&
  931. proto->recv_state != GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_ERROR)
  932. {
  933. char * response;
  934. globus_size_t response_len=0;
  935. globus_size_t offset;
  936. response_len += 1;
  937. response_len += strlen(GLOBUS_L_GENERIC_RESPONSE);
  938. response_len += 3;
  939. response_len += strlen(GLOBUS_L_OK);
  940. response_len += 2;
  941. response = globus_malloc(response_len);
  942. proto->state = GLOBUS_GASS_TRANSFER_HTTP_STATE_RESPONDING;
  943. offset = sprintf(response,
  944. GLOBUS_L_GENERIC_RESPONSE,
  945. 0,
  946. 200,
  947. GLOBUS_L_OK);
  948. offset += sprintf(response + offset,
  949. CRLF);
  950. debug_printf(4,(_GTSL("%s(): Registering write\n"),myname));
  951. globus_io_register_write(&proto->handle,
  952. (globus_byte_t *) response,
  953. strlen(response),
  954. globus_l_gass_transfer_http_write_response,
  955. proto);
  956. }
  957. /* Register the socket for closing if we're done reading from it */
  958. else if(proto->recv_state == GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_EOF ||
  959. proto->recv_state == GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_ERROR)
  960. {
  961. if(proto->state != GLOBUS_GASS_TRANSFER_HTTP_STATE_CLOSING)
  962. {
  963. result = globus_l_gass_transfer_http_register_close(proto);
  964. if (result != GLOBUS_SUCCESS)
  965. {
  966. globus_l_gass_transfer_http_close(proto);
  967. }
  968. }
  969. }
  970. if(proto->user_waitlen == 0 ||
  971. proto->recv_state == GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_EOF ||
  972. proto->recv_state == GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_ERROR)
  973. {
  974. globus_gass_transfer_request_t request;
  975. globus_bool_t last_data = GLOBUS_FALSE;
  976. globus_bool_t failure ;
  977. globus_byte_t * buf;
  978. globus_size_t offset;
  979. /*
  980. * Received the required minimum of data from connection, an
  981. * error, or the end-of file, signal this to GASS
  982. */
  983. if(proto->state == GLOBUS_GASS_TRANSFER_HTTP_STATE_PENDING)
  984. {
  985. proto->state = GLOBUS_GASS_TRANSFER_HTTP_STATE_IDLE;
  986. }
  987. if(proto->recv_state == GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_EOF ||
  988. proto->recv_state == GLOBUS_GASS_TRANSFER_HTTP_RECV_STATE_ERROR)
  989. {
  990. last_data = GLOBUS_TRUE;
  991. }
  992. if(err)
  993. {
  994. globus_object_free(err);
  995. err = GLOBUS_NULL;
  996. }
  997. proto->oneshot_active = GLOBUS_FALSE;
  998. failure = proto->failure_occurred;
  999. buf = proto->user_buffer;
  1000. offset = proto->user_offset;
  1001. request = proto->request;
  1002. globus_l_gass_transfer_http_signal();
  1003. globus_l_gass_transfer_http_unlock();
  1004. debug_printf(2, (_GTSL("calling globus_gass_transfer_proto_receive_complete()\n")));
  1005. globus_gass_transfer_proto_receive_complete(request,
  1006. buf,
  1007. offset,
  1008. failure,
  1009. last_data);
  1010. debug_printf(3, (_GTSL("Exiting %s()\n"),myname));
  1011. return;
  1012. }
  1013. else
  1014. {
  1015. result = globus_l_gass_transfer_http_register_read(proto);
  1016. }
  1017. if(result != GLOBUS_SUCCESS)
  1018. {
  1019. goto error_exit;
  1020. }
  1021. proto->oneshot_active = GLOBUS_FALSE;
  1022. globus_l_gass_transfer_http_unlock();
  1023. if(err)
  1024. {
  1025. globus_object_free(err);
  1026. }
  1027. debug_printf(3, (_GTSL("Exiting %s()\n"),myname));
  1028. return;
  1029. error_exit:
  1030. proto->state = GLOBUS_GASS_TRANSFER_HTTP_STATE_CLOSING;
  1031. proto->failure_occurred = GLOBUS_TRUE;
  1032. proto->oneshot_active = GLOBUS_FALSE;
  1033. proto->oneshot_active = GLOBUS_FALSE;
  1034. result = globus_l_gass_transfer_http_register_close(proto);
  1035. if(err)
  1036. {
  1037. globus_object_free(err);
  1038. }
  1039. {
  1040. globus_gass_transfer_request_t request;
  1041. globus_byte_t *buf;
  1042. globus_size_t offset;
  1043. request = proto->request;
  1044. buf = proto->user_buffer;
  1045. offset = proto->user_offset;
  1046. /* register close failed, act as though it was closed */
  1047. if (result != GLOBUS_SUCCESS)
  1048. {
  1049. globus_l_gass_transfer_http_close(proto);
  1050. }
  1051. globus_l_gass_transfer_http_unlock();
  1052. debug_printf(2, (_GTSL("calling globus_gass_transfer_proto_receive_complete()")));
  1053. globus_gass_transfer_proto_receive_complete(request,
  1054. buf,
  1055. offset,
  1056. GLOBUS_TRUE,
  1057. GLOBUS_TRUE);
  1058. }
  1059. debug_printf(3, (_GTSL("Exiting %s()\n"),myname));
  1060. return;
  1061. }
  1062. /* globus_l_gass_transfer_http_read_buffered_callback() */
  1063. /*
  1064. * Function: globus_l_gass_transfer_http_close_callback()
  1065. *
  1066. * Description: Called upon completion of close()ing the file handle,
  1067. * Will free the proto instance if the client has called
  1068. * the "done" function
  1069. *
  1070. *
  1071. * Parameters:
  1072. *
  1073. * Returns:
  1074. */
  1075. static
  1076. void
  1077. globus_l_gass_transfer_http_close_callback(
  1078. void * callback_arg,
  1079. globus_io_handle_t * handle,
  1080. globus_result_t result)
  1081. {
  1082. globus_gass_transfer_http_request_proto_t * proto;
  1083. MYNAME(globus_l_gass_transfer_http_close_callback);
  1084. debug_printf(3, (_GTSL("Entering %s()\n"),myname));
  1085. proto = (globus_gass_transfer_http_request_proto_t *) callback_arg;
  1086. globus_l_gass_transfer_http_lock();
  1087. globus_l_gass_transfer_http_close(proto);
  1088. globus_l_gass_transfer_http_unlock();
  1089. }
  1090. /* globus_l_gass_transfer_http_close_callback() */
  1091. /*
  1092. * Function: globus_l_gass_transfer_http_close()
  1093. *
  1094. * Description: must be called with the mutex locked
  1095. *
  1096. *
  1097. * Parameters:
  1098. *
  1099. * Returns:
  1100. */
  1101. static
  1102. void
  1103. globus_l_gass_transfer_http_close(
  1104. globus_gass_transfer_http_request_proto_t * proto)
  1105. {
  1106. proto->state = GLOBUS_GASS_TRANSFER_HTTP_STATE_DONE;
  1107. if(proto->destroy_called)
  1108. {
  1109. globus_l_gass_transfer_http_proto_destroy(proto);
  1110. }
  1111. globus_l_gass_transfer_http_closing--;
  1112. globus_l_gass_transfer_http_signal();
  1113. }
  1114. /* globus_l_gass_transfer_http_close() */
  1115. /*
  1116. * Function: globus_l_gass_transfer_http_register_close()
  1117. *
  1118. * Description: must be called with the mutex locked
  1119. *
  1120. *
  1121. * Parameters:
  1122. *
  1123. * Returns:
  1124. */
  1125. static
  1126. globus_result_t
  1127. globus_l_gass_transfer_http_register_close(
  1128. globus_gass_transfer_http_request_proto_t * proto)
  1129. {
  1130. globus_result_t result;
  1131. MYNAME(globus_l_gass_transfer_http_register_close);
  1132. proto->state = GLOBUS_GASS_TRANSFER_HTTP_STATE_CLOSING;
  1133. globus_l_gass_transfer_http_closing++;
  1134. debug_printf(4,(_GTSL("%s(): registering close on %p\n"), myname, &proto->handle));
  1135. result = globus_io_register_close(
  1136. &proto->handle,
  1137. globus_l_gass_transfer_http_close_callback,
  1138. proto);
  1139. return result;
  1140. }
  1141. /* globus_l_gass_transfer_http_register_close() */
  1142. /*
  1143. * Function: globus_l_gass_transfer_http_listener_close_callback()
  1144. *
  1145. * Description:
  1146. *
  1147. * Parameters:
  1148. *
  1149. * Returns:
  1150. */
  1151. static
  1152. void
  1153. globus_l_gass_transfer_http_listener_close_callback(
  1154. void * callback_arg,
  1155. globus_io_handle_t * handle,
  1156. globus_result_t result)
  1157. {
  1158. globus_gass_transfer_http_listener_proto_t *
  1159. proto;
  1160. MYNAME(globus_l_gass_transfer_http_listener_close_callback);
  1161. debug_printf(3, (_GTSL("Entering %s()\n"),myname));
  1162. proto = (globus_gass_transfer_http_listener_proto_t *) callback_arg;
  1163. globus_l_gass_transfer_http_lock();
  1164. globus_l_gass_transfer_http_listener_close(proto);
  1165. globus_l_gass_transfer_http_unlock();
  1166. debug_printf(3, (_GTSL("Exiting %s()\n"),myname));
  1167. }
  1168. /* globus_l_gass_transfer_http_listener_close_callback() */
  1169. /*
  1170. * Function: globus_l_gass_transfer_http_listener_close()
  1171. *
  1172. * Description: must be called with the mutex locked
  1173. *
  1174. * Parameters:
  1175. *
  1176. * Returns:
  1177. */
  1178. static
  1179. void
  1180. globus_l_gass_transfer_http_listener_close(
  1181. globus_gass_transfer_http_listener_proto_t * proto)
  1182. {
  1183. proto->state = GLOBUS_GASS_TRANSFER_HTTP_LISTENER_CLOSED;
  1184. if(proto->destroy_called)
  1185. {
  1186. globus_l_gass_transfer_http_listener_proto_destroy(proto);
  1187. }
  1188. globus_l_gass_transfer_http_closing--;
  1189. globus_l_gass_transfer_http_signal();
  1190. }
  1191. /* globus_l_gass_transfer_http_listener_close() */
  1192. static
  1193. void
  1194. globus_l_gass_transfer_http_register_listener_close(
  1195. globus_gass_transfer_http_listener_proto_t * proto)
  1196. {
  1197. globus_result_t result;
  1198. MYNAME(globus_l_gass_transfer_http_register_listener_close);
  1199. globus_l_gass_transfer_http_closing++;
  1200. debug_printf(4,(_GTSL("%s(): registering close on %p\n"), myname, &proto->handle));
  1201. result = globus_io_register_close(
  1202. &proto->handle,
  1203. globus_l_gass_transfer_http_listener_close_callback,
  1204. proto);
  1205. globus_assert(result == GLOBUS_SUCCESS);
  1206. if(result != GLOBUS_SUCCESS)
  1207. {
  1208. globus_l_gass_transfer_http_listener_close(proto);
  1209. }
  1210. }
  1211. /* globus_l_gass_transfer_http_register_listener_close() */
  1212. /*
  1213. * Function: globus_l_gass_transfer_http_listener_proto_destroy()
  1214. *
  1215. * Description:
  1216. *
  1217. * Parameters:
  1218. *
  1219. * Returns:
  1220. */
  1221. static
  1222. void
  1223. globus_l_gass_transfer_http_listener_proto_destroy(
  1224. globus_gass_transfer_http_listener_proto_t *
  1225. proto)
  1226. {
  1227. globus_free(proto);
  1228. }
  1229. /* globus_l_gass_transfer_http_listener_proto_destroy() */
  1230. /*
  1231. * Function: globus_l_gass_transfer_http_destroy()
  1232. *
  1233. * Description:
  1234. *
  1235. * Parameters:
  1236. *
  1237. * Returns:
  1238. */
  1239. static
  1240. void
  1241. globus_l_gass_transfer_http_destroy(
  1242. globus_gass_transfer_request_proto_t * proto,
  1243. globus_gass_transfer_request_t request)
  1244. {
  1245. globus_gass_transfer_http_request_proto_t * new_proto;
  1246. MYNAME(globus_l_gass_transfer_http_destroy);
  1247. debug_printf(1, (_GTSL("entering %s()\n"),myname));
  1248. new_proto = (globus_gass_transfer_http_request_proto_t *) proto;
  1249. globus_l_gass_transfer_http_lock();
  1250. if(new_proto->state == GLOBUS_GASS_TRANSFER_HTTP_STATE_CLOSING ||
  1251. new_proto->state == GLOBUS_GASS_TRANSFER_HTTP_STATE_REFERRED ||
  1252. new_proto->state == GLOBUS_GASS_TRANSFER_HTTP_STATE_RESPONDING ||
  1253. new_proto->state == GLOBUS_GASS_TRANSFER_HTTP_STATE_DENIED)
  1254. {
  1255. new_proto->destroy_called=GLOBUS_TRUE;
  1256. }
  1257. else if(new_proto->state == GLOBUS_GASS_TRANSFER_HTTP_STATE_DONE)
  1258. {
  1259. globus_l_gass_transfer_http_proto_destroy(new_proto);
  1260. }
  1261. globus_l_gass_transfer_http_unlock();
  1262. debug_printf(1, (_GTSL("exiting %s()\n"),myname));
  1263. }
  1264. /* globus_l_gass_transfer_http_destroy() */
  1265. /*
  1266. * Function: globus_l_gass_transfer_http_listener_destroy()
  1267. *
  1268. * Description:
  1269. *
  1270. * Parameters:
  1271. *
  1272. * Returns:
  1273. */
  1274. static
  1275. void
  1276. globus_l_gass_transfer_http_listener_destroy(
  1277. globus_gass_transfer_listener_proto_t * proto,
  1278. globus_gass_transfer_listener_t listener)
  1279. {
  1280. globus_gass_transfer_http_listener_proto_t *new_proto;
  1281. MYNAME(globus_l_gass_transfer_http_listener_destroy);
  1282. debug_printf(1, (_GTSL("entering %s()\n"),myname));
  1283. new_proto = (globus_gass_transfer_http_listener_proto_t *) proto;
  1284. globus_l_gass_transfer_http_lock();
  1285. if(new_proto->state != GLOBUS_GASS_TRANSFER_HTTP_LISTENER_CLOSED)
  1286. {
  1287. new_proto->destroy_called=GLOBUS_TRUE;
  1288. }
  1289. else
  1290. {
  1291. globus_l_gass_transfer_http_listener_proto_destroy(new_proto);
  1292. }
  1293. globus_l_gass_transfer_http_unlock();
  1294. debug_printf(1, (_GTSL("exiting %s()\n"),myname));
  1295. }
  1296. /* globus_l_gass_transfer_http_listener_destroy() */
  1297. /*
  1298. * Function: globus_l_gass_transfer_http_listen()
  1299. *
  1300. * Description:
  1301. *
  1302. * Parameters:
  1303. *
  1304. * Returns:
  1305. */
  1306. static
  1307. void
  1308. globus_l_gass_transfer_http_listen(
  1309. globus_gass_transfer_listener_proto_t * proto,
  1310. globus_gass_transfer_listener_t listener)
  1311. {
  1312. globus_gass_transfer_http_listener_proto_t *new_proto;
  1313. globus_result_t result;
  1314. globus_reltime_t delay_time;
  1315. MYNAME(globus_l_gass_transfer_http_listen);
  1316. debug_printf(1, (_GTSL("entering %s()\n"),myname));
  1317. new_proto = (globus_gass_transfer_http_listener_proto_t *) proto;
  1318. globus_l_gass_transfer_http_lock();
  1319. debug_printf(4,(_GTSL("%s(): registering listen on %p\n"),
  1320. myname,
  1321. &new_proto->handle));
  1322. result = globus_io_tcp_register_listen(
  1323. &new_proto->handle,
  1324. globus_l_gass_transfer_http_listen_callback,
  1325. (void *) new_proto);
  1326. if(result != GLOBUS_SUCCESS)
  1327. {
  1328. GlobusTimeReltimeSet(delay_time, 0, 0);
  1329. debug_printf(4,(_GTSL("%s(): registering oneshot because listen failed\n"),
  1330. myname));
  1331. globus_callback_register_oneshot(
  1332. GLOBUS_NULL,
  1333. &delay_time,
  1334. globus_l_gass_transfer_http_callback_listen_callback,
  1335. (void *) new_proto);
  1336. }
  1337. else
  1338. {
  1339. new_proto->state = GLOBUS_GASS_TRANSFER_HTTP_LISTENER_LISTENING;
  1340. }
  1341. globus_l_gass_transfer_http_unlock();
  1342. debug_printf(1, (_GTSL("exiting %s()\n"),myname));
  1343. }
  1344. /* globus_l_gass_transfer_http_listen() */
  1345. static
  1346. void
  1347. globus_l_gass_transfer_http_listen_callback(
  1348. void * callback_arg,
  1349. globus_io_handle_t * handle,
  1350. globus_result_t result)
  1351. {
  1352. globus_gass_transfer_http_listener_proto_t *proto;
  1353. globus_gass_transfer_listener_t listener;
  1354. MYNAME(globus_l_gass_transfer_http_listen_callback);
  1355. debug_printf(3, (_GTSL("Entering %s()\n"),myname));
  1356. proto = (globus_gass_transfer_http_listener_proto_t *) callback_arg;
  1357. globus_l_gass_transfer_http_lock();
  1358. switch(proto->state)
  1359. {
  1360. case GLOBUS_GASS_TRANSFER_HTTP_LISTENER_LISTENING:
  1361. proto->state = GLOBUS_GASS_TRANSFER_HTTP_LISTENER_READY;
  1362. break;
  1363. case GLOBUS_GASS_TRANSFER_HTTP_LISTENER_CLOSING1:
  1364. case GLOBUS_GASS_TRANSFER_HTTP_LISTENER_CLOSED:
  1365. break;
  1366. case GLOBUS_GASS_TRANSFER_HTTP_LISTENER_STARTING:
  1367. case GLOBUS_GASS_TRANSFER_HTTP_LISTENER_ACCEPTING:
  1368. case GLOBUS_GASS_TRANSFER_HTTP_LISTENER_READY:
  1369. case GLOBUS_GASS_TRANSFER_HTTP_LISTENER_CLOSING2:
  1370. globus_assert(proto->state != GLOBUS_GASS_TRANSFER_HTTP_LISTENER_STARTING);
  1371. globus_assert(proto->state != GLOBUS_GASS_TRANSFER_HTTP_LISTENER_ACCEPTING);
  1372. globus_assert(proto->state != GLOBUS_GASS_TRANSFER_HTTP_LISTENER_READY);
  1373. globus_assert(proto->state != GLOBUS_GASS_TRANSFER_HTTP_LISTENER_CLOSING2);
  1374. }
  1375. listener = proto->listener;
  1376. globus_l_gass_transfer_http_unlock();
  1377. debug_printf(2, (_GTSL("calling globus_gass_transfer_proto_listener_ready()")));
  1378. globus_gass_transfer_proto_listener_ready(listener);
  1379. debug_printf(3, (_GTSL("Exiting %s()\n"),myname));
  1380. }
  1381. /* globus_l_gass_transfer_http_listen_callback() */
  1382. static
  1383. void
  1384. globus_l_gass_transfer_http_accept_callback(
  1385. void * callback_arg,
  1386. globus_io_handle_t * handle,
  1387. globus_result_t result)
  1388. {
  1389. globus_gass_transfer_http_listener_proto_t *l;
  1390. MYNAME(globus_l_gass_transfer_http_accept_callback);
  1391. debug_printf(3, (_GTSL("Entering %s()\n"),myname));
  1392. globus_l_gass_transfer_http_lock();
  1393. fflush(stdout);
  1394. l = (globus_gass_transfer_http_listener_proto_t *) callback_arg;
  1395. switch(l->state)
  1396. {
  1397. case GLOBUS_GASS_TRANSFER_HTTP_LISTENER_ACCEPTING:
  1398. l->request->response_buffer = globus_malloc(GLOBUS_L_GASS_RESPONSE_LEN *
  1399. sizeof(globus_byte_t));
  1400. l->request->response_buflen = GLOBUS_L_GASS_RESPONSE_LEN;
  1401. l->request->response_offset = 0;
  1402. l->request->parsed_offset = 0;
  1403. if(result != GLOBUS_SUCCESS)
  1404. {
  1405. globus_l_gass_transfer_http_unlock();
  1406. globus_l_gass_transfer_http_request_callback(
  1407. l,
  1408. &l->request->handle,
  1409. result,
  1410. l->request->response_buffer,
  1411. 0);
  1412. debug_printf(3, (_GTSL("Exiting globus_l_gass_transfer_http_accept_callback()\n")));
  1413. return;
  1414. }
  1415. else
  1416. {
  1417. debug_printf(4, (_GTSL("%s(): Registering read on %p\n"),
  1418. myname,
  1419. &l->request->handle));
  1420. globus_io_register_read(&l->request->handle,
  1421. l->request->response_buffer,
  1422. l->request->response_buflen,
  1423. 1,
  1424. globus_l_gass_transfer_http_request_callback,
  1425. l);
  1426. }
  1427. break;
  1428. case GLOBUS_GASS_TRANSFER_HTTP_LISTENER_CLOSING2:
  1429. case GLOBUS_GASS_TRANSFER_HTTP_LISTENER_CLOSED:
  1430. globus_l_gass_transfer_http_unlock();
  1431. globus_gass_transfer_proto_new_listener_request(l->listener,
  1432. l->request->request,
  1433. GLOBUS_NULL);
  1434. globus_l_gass_transfer_http_lock();
  1435. /* should destroy the proto->request here? */
  1436. break;
  1437. case GLOBUS_GASS_TRANSFER_HTTP_LISTENER_STARTING:
  1438. case GLOBUS_GASS_TRANSFER_HTTP_LISTENER_LISTENING:
  1439. case GLOBUS_GASS_TRANSFER_HTTP_LISTENER_READY:
  1440. case GLOBUS_GASS_TRANSFER_HTTP_LISTENER_CLOSING1:
  1441. globus_assert(l->state != GLOBUS_GASS_TRANSFER_HTTP_LISTENER_STARTING);
  1442. globus_assert(l->state != GLOBUS_GASS_TRANSFER_HTTP_LISTENER_LISTENING);
  1443. globus_assert(l->state != GLOBUS_GASS_TRANSFER_HTTP_LISTENER_READY);
  1444. globus_assert(l->state != GLOBUS_GASS_TRANSFER_HTTP_LISTENER_CLOSING1);
  1445. }
  1446. globus_l_gass_transfer_http_unlock();
  1447. debug_printf(3, (_GTSL("Exiting %s()\n"), myname));
  1448. }
  1449. /* globus_l_gass_transfer_http_accept_callback() */
  1450. static
  1451. void
  1452. globus_l_gass_transfer_http_request_refer(
  1453. globus_gass_transfer_request_proto_t * rproto,
  1454. globus_gass_transfer_request_t request)
  1455. {
  1456. globus_gass_transfer_http_request_proto_t * proto;
  1457. globus_gass_transfer_referral_t referral;
  1458. int rc;
  1459. char * referral_string;
  1460. globus_size_t referral_count;
  1461. globus_size_t body_count=0; /* :) */
  1462. globus_size_t offset;
  1463. globus_size_t x;
  1464. globus_size_t i;
  1465. globus_size_t digits = 0;
  1466. MYNAME(globus_l_gass_transfer_http_request_refer);
  1467. globus_l_gass_transfer_http_lock();
  1468. proto = (globus_gass_transfer_http_request_proto_t *) rproto;
  1469. rc = globus_gass_transfer_request_get_referral(request,
  1470. &referral);
  1471. /* HTTP/1.1 302 Document Moved CRLF
  1472. * Location: referral.url[0] CRLF
  1473. * Content-Length: $body_count CRLF
  1474. * Content-Type: text/html CRLF
  1475. * CRLF
  1476. * <html><head><title>300 Multiple Choices</title></head><body>
  1477. * <a href="<referral.url[1]>">referral.url[1]</a><br>
  1478. * ..
  1479. * <a href="<referral.url[i]>">referral.url[i]</a><br>
  1480. * </body></html>
  1481. */
  1482. referral_count = 1;
  1483. referral_count += strlen(GLOBUS_L_REFER_RESPONSE);
  1484. referral_count += strlen(GLOBUS_L_LOCATION_HEADER);
  1485. referral_count += 2;
  1486. referral_count += strlen(GLOBUS_L_CONTENT_LENGTH_HEADER);
  1487. referral_count += strlen(GLOBUS_L_HTML_HEADER);
  1488. referral_count += strlen(referral.url[0]);
  1489. body_count += strlen(GLOBUS_L_HTML_REFERRAL_BODY_HEAD);
  1490. body_count += strlen(GLOBUS_L_HTML_REFERRAL_BODY_TAIL);
  1491. for(i = 0 ; i < referral.count; i++)
  1492. {
  1493. body_count += strlen(GLOBUS_L_HTML_HREF);
  1494. body_count += strlen(referral.url[i]);
  1495. body_count += strlen(referral.url[i]);
  1496. }
  1497. /* count the number of decimal digits in the body */
  1498. x=body_count;
  1499. do
  1500. {
  1501. digits++;
  1502. x /= 10;
  1503. } while(x > 0);
  1504. referral_count += digits;
  1505. referral_string = globus_malloc(referral_count + body_count);
  1506. offset = sprintf(referral_string,
  1507. GLOBUS_L_REFER_RESPONSE);
  1508. offset += sprintf(referral_string + offset,
  1509. GLOBUS_L_LOCATION_HEADER,
  1510. referral.url[0]);
  1511. offset += sprintf(referral_string + offset,
  1512. GLOBUS_L_HTML_HEADER);
  1513. offset += sprintf(referral_string + offset,
  1514. GLOBUS_L_CONTENT_LENGTH_HEADER,
  1515. (long) body_count);
  1516. offset += sprintf(referral_string + offset,
  1517. CRLF);
  1518. offset += sprintf(referral_string + offset,
  1519. GLOBUS_L_HTML_REFERRAL_BODY_HEAD);
  1520. for(i = 0 ; i < referral.count; i++)
  1521. {
  1522. offset += sprintf(referral_string + offset,
  1523. GLOBUS_L_HTML_HREF,
  1524. referral.url[i],
  1525. referral.url[i]);
  1526. }
  1527. offset += sprintf(referral_string + offset,
  1528. GLOBUS_L_HTML_REFERRAL_BODY_TAIL);
  1529. proto->state = GLOBUS_GASS_TRANSFER_HTTP_STATE_REFERRED;
  1530. globus_gass_transfer_referral_destroy(&referral);
  1531. debug_printf(4, (_GTSL("%s(): Registering write on %p\n"),
  1532. myname,
  1533. &proto->handle));
  1534. globus_io_register_write(&proto->handle,
  1535. (globus_byte_t *) referral_string,
  1536. strlen(referral_string),
  1537. globus_l_gass_transfer_http_write_response,
  1538. proto);
  1539. globus_l_gass_transfer_http_unlock();
  1540. }
  1541. /* globus_l_gass_transfer_http_request_refer() */
  1542. static
  1543. void
  1544. globus_l_gass_transfer_http_request_deny(
  1545. globus_gass_transfer_request_proto_t * rproto,
  1546. globus_gass_transfer_request_t request)
  1547. {
  1548. globus_gass_transfer_http_request_proto_t * proto;
  1549. char * deny_string;
  1550. globus_size_t deny_count;
  1551. globus_size_t body_count=0; /* :) */
  1552. globus_size_t offset;
  1553. globus_size_t x;
  1554. globus_size_t digits = 0;
  1555. int reason;
  1556. char * message;
  1557. MYNAME(globus_l_gass_transfer_http_request_deny);
  1558. globus_l_gass_transfer_http_lock();
  1559. proto = (globus_gass_transfer_http_request_proto_t *) rproto;
  1560. reason = globus_gass_transfer_request_get_denial_reason(request);
  1561. if(reason < 400 ||
  1562. reason >= 600)
  1563. {
  1564. reason = 500;
  1565. message = globus_libc_strdup(GLOBUS_L_

Large files files are truncated, but you can click here to view the full file