Actual source code: globus.c
1: #include <petscwebclient.h>
2: #pragma clang diagnostic ignored "-Wdeprecated-declarations"
3: #pragma gcc diagnostic ignored "-Wdeprecated-declarations"
5: /*
6: Encodes and decodes from MIME Base64
7: */
8: static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
9: 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
11: static PetscErrorCode base64_encode(const unsigned char *data, unsigned char *encoded_data, size_t len)
12: {
13: static size_t mod_table[] = {0, 2, 1};
14: size_t i, j;
15: size_t input_length, output_length;
17: PetscStrlen((const char *)data, &input_length);
18: output_length = 4 * ((input_length + 2) / 3);
21: for (i = 0, j = 0; i < input_length;) {
22: uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
23: uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
24: uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
25: uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
27: encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
28: encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
29: encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
30: encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
31: }
32: encoded_data[j] = 0;
33: for (i = 0; i < mod_table[input_length % 3]; i++) encoded_data[output_length - 1 - i] = '=';
34: return 0;
35: }
37: PETSC_UNUSED static PetscErrorCode base64_decode(const unsigned char *data, unsigned char *decoded_data, size_t length)
38: {
39: static char decoding_table[257];
40: static int decode_table_built = 0;
41: size_t i, j;
42: size_t input_length, output_length;
44: if (!decode_table_built) {
45: for (i = 0; i < 64; i++) decoding_table[(unsigned char)encoding_table[i]] = i;
46: decode_table_built = 1;
47: }
49: PetscStrlen((const char *)data, &input_length);
52: output_length = input_length / 4 * 3;
53: if (data[input_length - 1] == '=') (output_length)--;
54: if (data[input_length - 2] == '=') (output_length)--;
57: for (i = 0, j = 0; i < input_length;) {
58: uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
59: uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
60: uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
61: uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
62: uint32_t triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6);
64: if (j < output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
65: if (j < output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
66: if (j < output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
67: }
68: decoded_data[j] = 0;
69: return 0;
70: }
72: #if defined(PETSC_HAVE_UNISTD_H)
73: #include <unistd.h>
74: #endif
76: /*@C
77: PetscGlobusAuthorize - Get an access token allowing PETSc applications to make Globus file transfer requests
79: Not collective, only the first process in `MPI_Comm` does anything
81: Input Parameters:
82: + comm - the MPI communicator
83: - tokensize - size of the token array
85: Output Parameters:
86: . access_token - can be used with `PetscGlobusUpLoad()` for 30 days
88: Notes:
89: This call requires stdout and stdin access from process 0 on the MPI communicator
91: You can run src/sys/webclient/tutorials/globusobtainaccesstoken to get an access token
93: Level: intermediate
95: .seealso: `PetscGoogleDriveRefresh()`, `PetscGoogleDriveUpload()`, `PetscURLShorten()`, `PetscGlobusUpload()`
96: @*/
97: PetscErrorCode PetscGlobusAuthorize(MPI_Comm comm, char access_token[], size_t tokensize)
98: {
99: SSL_CTX *ctx;
100: SSL *ssl;
101: int sock;
102: char buff[8 * 1024], *ptr, head[1024];
103: PetscMPIInt rank;
104: size_t len;
105: PetscBool found;
107: MPI_Comm_rank(comm, &rank);
108: if (rank == 0) {
110: PetscPrintf(comm, "Enter globus username:");
111: ptr = fgets(buff, 1024, stdin);
113: PetscStrlen(buff, &len);
114: buff[len - 1] = ':'; /* remove carriage return at end of line */
116: PetscPrintf(comm, "Enter globus password:");
117: ptr = fgets(buff + len, 1024 - len, stdin);
119: PetscStrlen(buff, &len);
120: buff[len - 1] = '\0'; /* remove carriage return at end of line */
121: PetscStrcpy(head, "Authorization: Basic ");
122: base64_encode((const unsigned char *)buff, (unsigned char *)(head + 21), sizeof(head) - 21);
123: PetscStrcat(head, "\r\n");
125: PetscSSLInitializeContext(&ctx);
126: PetscHTTPSConnect("nexus.api.globusonline.org", 443, ctx, &sock, &ssl);
127: PetscHTTPSRequest("GET", "nexus.api.globusonline.org/goauth/token?grant_type=client_credentials", head, "application/x-www-form-urlencoded", NULL, ssl, buff, sizeof(buff));
128: PetscSSLDestroyContext(ctx);
129: close(sock);
131: PetscPullJSONValue(buff, "access_token", access_token, tokensize, &found);
134: PetscPrintf(comm, "Here is your Globus access token, save it in a save place, in the future you can run PETSc\n");
135: PetscPrintf(comm, "programs with the option -globus_access_token %s\n", access_token);
136: PetscPrintf(comm, "to access Globus automatically\n");
137: }
138: return 0;
139: }
141: /*@C
142: PetscGlobusGetTransfers - Get a record of current transfers requested from Globus
144: Not collective, only the first process in `MPI_Comm` does anything
146: Input Parameters:
147: + comm - the MPI communicator
148: . access_token - Globus access token, if NULL will check in options database for -globus_access_token XXX otherwise
149: will call `PetscGlobusAuthorize()`.
150: - buffsize - size of the buffer
152: Output Parameters:
153: . buff - location to put Globus information
155: Level: intermediate
157: .seealso: `PetscGoogleDriveRefresh()`, `PetscGoogleDriveUpload()`, `PetscURLShorten()`, `PetscGlobusUpload()`, `PetscGlobusAuthorize()`
158: @*/
159: PetscErrorCode PetscGlobusGetTransfers(MPI_Comm comm, const char access_token[], char buff[], size_t buffsize)
160: {
161: SSL_CTX *ctx;
162: SSL *ssl;
163: int sock;
164: char head[4096];
165: PetscMPIInt rank;
167: MPI_Comm_rank(comm, &rank);
168: if (rank == 0) {
169: PetscStrcpy(head, "Authorization : Globus-Goauthtoken ");
170: if (access_token) {
171: PetscStrcat(head, access_token);
172: } else {
173: PetscBool set;
174: char accesstoken[4096];
175: PetscOptionsGetString(NULL, NULL, "-globus_access_token", accesstoken, sizeof(accesstoken), &set);
177: PetscStrcat(head, accesstoken);
178: }
179: PetscStrcat(head, "\r\n");
181: PetscSSLInitializeContext(&ctx);
182: PetscHTTPSConnect("transfer.api.globusonline.org", 443, ctx, &sock, &ssl);
183: PetscHTTPSRequest("GET", "transfer.api.globusonline.org/v0.10/tasksummary", head, "application/json", NULL, ssl, buff, buffsize);
184: PetscSSLDestroyContext(ctx);
185: close(sock);
186: }
187: return 0;
188: }
190: /*@C
191: PetscGlobusUpload - Loads a file to Globus
193: Not collective, only the first process in the `MPI_Comm` uploads the file
195: Input Parameters:
196: + comm - MPI communicator
197: . access_token - obtained with `PetscGlobusAuthorize()`, pass NULL to use -globus_access_token XXX from the PETSc database
198: - filename - file to upload
200: Options Database Key:
201: . -globus_access_token XXX - the Globus token
203: Level: intermediate
205: .seealso: `PetscURLShorten()`, `PetscGoogleDriveAuthorize()`, `PetscGoogleDriveRefresh()`, `PetscGlobusAuthorize()`
206: @*/
207: PetscErrorCode PetscGlobusUpload(MPI_Comm comm, const char access_token[], const char filename[])
208: {
209: SSL_CTX *ctx;
210: SSL *ssl;
211: int sock;
212: char head[4096], buff[8 * 1024], body[4096], submission_id[4096];
213: PetscMPIInt rank;
214: PetscBool flg, found;
216: MPI_Comm_rank(comm, &rank);
217: if (rank == 0) {
218: PetscTestFile(filename, 'r', &flg);
221: PetscStrcpy(head, "Authorization : Globus-Goauthtoken ");
222: if (access_token) {
223: PetscStrcat(head, access_token);
224: } else {
225: PetscBool set;
226: char accesstoken[4096];
227: PetscOptionsGetString(NULL, NULL, "-globus_access_token", accesstoken, sizeof(accesstoken), &set);
229: PetscStrcat(head, accesstoken);
230: }
231: PetscStrcat(head, "\r\n");
233: /* Get Globus submission id */
234: PetscSSLInitializeContext(&ctx);
235: PetscHTTPSConnect("transfer.api.globusonline.org", 443, ctx, &sock, &ssl);
236: PetscHTTPSRequest("GET", "transfer.api.globusonline.org/v0.10/submission_id", head, "application/json", NULL, ssl, buff, sizeof(buff));
237: PetscSSLDestroyContext(ctx);
238: close(sock);
239: PetscPullJSONValue(buff, "value", submission_id, sizeof(submission_id), &found);
242: /* build JSON body of transfer request */
243: PetscStrcpy(body, "{");
244: PetscPushJSONValue(body, "submission_id", submission_id, sizeof(body));
245: PetscStrcat(body, ",");
246: PetscPushJSONValue(body, "DATA_TYPE", "transfer", sizeof(body));
247: PetscStrcat(body, ",");
248: PetscPushJSONValue(body, "sync_level", "null", sizeof(body));
249: PetscStrcat(body, ",");
250: PetscPushJSONValue(body, "source_endpoint", "barryfsmith#MacBookPro", sizeof(body));
251: PetscStrcat(body, ",");
252: PetscPushJSONValue(body, "label", "PETSc transfer label", sizeof(body));
253: PetscStrcat(body, ",");
254: PetscPushJSONValue(body, "length", "1", sizeof(body));
255: PetscStrcat(body, ",");
256: PetscPushJSONValue(body, "destination_endpoint", "mcs#home", sizeof(body));
257: PetscStrcat(body, ",");
259: PetscStrcat(body, "\"DATA\": [ {");
260: PetscPushJSONValue(body, "source_path", "/~/FEM_GPU.pdf", sizeof(body));
261: PetscStrcat(body, ",");
262: PetscPushJSONValue(body, "destination_path", "/~/FEM_GPU.pdf", sizeof(body));
263: PetscStrcat(body, ",");
264: PetscPushJSONValue(body, "verify_size", "null", sizeof(body));
265: PetscStrcat(body, ",");
266: PetscPushJSONValue(body, "recursive", "false", sizeof(body));
267: PetscStrcat(body, ",");
268: PetscPushJSONValue(body, "DATA_TYPE", "transfer_item", sizeof(body));
269: PetscStrcat(body, "} ] }");
271: PetscSSLInitializeContext(&ctx);
272: PetscHTTPSConnect("transfer.api.globusonline.org", 443, ctx, &sock, &ssl);
273: PetscHTTPSRequest("POST", "transfer.api.globusonline.org/v0.10/transfer", head, "application/json", body, ssl, buff, sizeof(buff));
274: PetscSSLDestroyContext(ctx);
275: close(sock);
276: PetscPullJSONValue(buff, "code", submission_id, sizeof(submission_id), &found);
278: PetscStrcmp(submission_id, "Accepted", &found);
280: }
281: return 0;
282: }