Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(353)

Side by Side Diff: native_client_sdk/src/examples/demo/nacl_io/handlers.c

Issue 306973002: [NaCl SDK] rename nacl_io demo. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /* Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file. */
4
5 #include "handlers.h"
6
7 #include <arpa/inet.h>
8 #include <assert.h>
9 #include <errno.h>
10 #include <limits.h>
11 #include <netdb.h>
12 #include <netinet/in.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <unistd.h>
17
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <sys/stat.h>
21
22 #include "nacl_io/osdirent.h"
23
24 #include "nacl_io_demo.h"
25
26 #define MAX_OPEN_FILES 10
27 #define MAX_OPEN_DIRS 10
28 #define MAX_PARAMS 4
29
30 #if defined(WIN32)
31 #define stat _stat
32 #endif
33
34 /**
35 * A mapping from int -> FILE*, so the JavaScript messages can refer to an open
36 * File.
37 */
38 static FILE* g_OpenFiles[MAX_OPEN_FILES];
39
40 /**
41 * A mapping from int -> DIR*, so the JavaScript messages can refer to an open
42 * Directory.
43 */
44 static void* g_OpenDirs[MAX_OPEN_DIRS];
45
46 /**
47 * A collection of the most recently allocated parameter strings. This makes
48 * the Handle* functions below easier to write because they don't have to
49 * manually deallocate the strings they're using.
50 */
51 static char* g_ParamStrings[MAX_PARAMS];
52
53 /**
54 * Add |object| to |map| and return the index it was added at.
55 * @param[in] map The map to add the object to.
56 * @param[in] max_map_size The maximum map size.
57 * @param[in] object The object to add to the map.
58 * @return int The index of the added object, or -1 if there is no more space.
59 */
60 static int AddToMap(void** map, int max_map_size, void* object) {
61 int i;
62 assert(object != NULL);
63 for (i = 0; i < max_map_size; ++i) {
64 if (map[i] == NULL) {
65 map[i] = object;
66 return i;
67 }
68 }
69
70 return -1;
71 }
72
73 /**
74 * Remove an object at index |i| from |map|.
75 * @param[in] map The map to remove from.
76 * @param[in] max_map_size The size of the map.
77 * @param[in] i The index to remove.
78 */
79 static void RemoveFromMap(void** map, int max_map_size, int i) {
80 assert(i >= 0 && i < max_map_size);
81 map[i] = NULL;
82 }
83
84 /**
85 * Add the file to the g_OpenFiles map.
86 * @param[in] file The file to add to g_OpenFiles.
87 * @return int The index of the FILE in g_OpenFiles, or -1 if there are too many
88 * open files.
89 */
90 static int AddFileToMap(FILE* file) {
91 return AddToMap((void**)g_OpenFiles, MAX_OPEN_FILES, file);
92 }
93
94 /**
95 * Remove the file from the g_OpenFiles map.
96 * @param[in] i The index of the file handle to remove.
97 */
98 static void RemoveFileFromMap(int i) {
99 RemoveFromMap((void**)g_OpenFiles, MAX_OPEN_FILES, i);
100 }
101
102 /* Win32 doesn't support DIR/opendir/readdir/closedir. */
103 #if !defined(WIN32)
104 /**
105 * Add the dir to the g_OpenDirs map.
106 * @param[in] dir The dir to add to g_OpenDirs.
107 * @return int The index of the DIR in g_OpenDirs, or -1 if there are too many
108 * open dirs.
109 */
110 static int AddDirToMap(DIR* dir) {
111 return AddToMap((void**)g_OpenDirs, MAX_OPEN_DIRS, dir);
112 }
113
114 /**
115 * Remove the dir from the g_OpenDirs map.
116 * @param[in] i The index of the dir handle to remove.
117 */
118 static void RemoveDirFromMap(int i) {
119 RemoveFromMap((void**)g_OpenDirs, MAX_OPEN_DIRS, i);
120 }
121 #endif
122
123 /**
124 * Get the number of parameters.
125 * @param[in] params The parameter array.
126 * @return uint32_t The number of parameters in the array.
127 */
128 static uint32_t GetNumParams(struct PP_Var params) {
129 return g_ppb_var_array->GetLength(params);
130 }
131
132 /**
133 * Get a parameter at |index| as a string.
134 * @param[in] params The parameter array.
135 * @param[in] index The index in |params| to get.
136 * @param[out] out_string The output string.
137 * @param[out] out_string_len The length of the output string.
138 * @param[out] out_error An error message, if this operation failed.
139 * @return int 0 if successful, otherwise 1.
140 */
141 static int GetParamString(struct PP_Var params,
142 uint32_t index,
143 char** out_string,
144 uint32_t* out_string_len,
145 const char** out_error) {
146 if (index >= MAX_PARAMS) {
147 *out_error = PrintfToNewString("Param index %u >= MAX_PARAMS (%d)",
148 index, MAX_PARAMS);
149 return 1;
150 }
151
152 struct PP_Var value = g_ppb_var_array->Get(params, index);
153 if (value.type != PP_VARTYPE_STRING) {
154 *out_error =
155 PrintfToNewString("Expected param at index %d to be a string", index);
156 return 1;
157 }
158
159 uint32_t length;
160 const char* var_str = g_ppb_var->VarToUtf8(value, &length);
161
162 char* string = (char*)malloc(length + 1);
163 memcpy(string, var_str, length);
164 string[length] = 0;
165
166 /* Put the allocated string in g_ParamStrings. This keeps us from leaking
167 * each parameter string, without having to do manual cleanup in every
168 * Handle* function below.
169 */
170 free(g_ParamStrings[index]);
171 g_ParamStrings[index] = string;
172
173
174 *out_string = string;
175 *out_string_len = length;
176 return 0;
177 }
178
179 /**
180 * Get a parameter at |index| as a FILE*.
181 * @param[in] params The parameter array.
182 * @param[in] index The index in |params| to get.
183 * @param[out] out_file The output FILE*.
184 * @param[out] out_file_index The index of the output FILE* in g_OpenFiles.
185 * @param[out] out_error An error message, if this operation failed.
186 * @return int 0 if successful, otherwise 1.
187 */
188 static int GetParamFile(struct PP_Var params,
189 uint32_t index,
190 FILE** out_file,
191 int32_t* out_file_index,
192 const char** out_error) {
193 struct PP_Var value = g_ppb_var_array->Get(params, index);
194 if (value.type != PP_VARTYPE_INT32) {
195 *out_error =
196 PrintfToNewString("Expected param at index %d to be an int32", index);
197 return 1;
198 }
199
200 int32_t file_index = value.value.as_int;
201 if (file_index < 0 || file_index >= MAX_OPEN_FILES) {
202 *out_error = PrintfToNewString("File index %d is out range", file_index);
203 return 1;
204 }
205
206 if (g_OpenFiles[file_index] == NULL) {
207 *out_error = PrintfToNewString("File index %d is not open", file_index);
208 return 1;
209 }
210
211 *out_file = g_OpenFiles[file_index];
212 *out_file_index = file_index;
213 return 0;
214 }
215
216 /**
217 * Get a parameter at |index| as a DIR*.
218 * @param[in] params The parameter array.
219 * @param[in] index The index in |params| to get.
220 * @param[out] out_file The output DIR*.
221 * @param[out] out_file_index The index of the output DIR* in g_OpenDirs.
222 * @param[out] out_error An error message, if this operation failed.
223 * @return int 0 if successful, otherwise 1.
224 */
225 static int GetParamDir(struct PP_Var params,
226 uint32_t index,
227 DIR** out_dir,
228 int32_t* out_dir_index,
229 const char** out_error) {
230 struct PP_Var value = g_ppb_var_array->Get(params, index);
231 if (value.type != PP_VARTYPE_INT32) {
232 *out_error =
233 PrintfToNewString("Expected param at index %d to be an int32", index);
234 return 1;
235 }
236
237 int32_t dir_index = value.value.as_int;
238 if (dir_index < 0 || dir_index >= MAX_OPEN_DIRS) {
239 *out_error = PrintfToNewString("Dir at index %d is out range", dir_index);
240 return 1;
241 }
242
243 if (g_OpenDirs[dir_index] == NULL) {
244 *out_error = PrintfToNewString("Dir index %d is not open", dir_index);
245 return 1;
246 }
247
248 *out_dir = g_OpenDirs[dir_index];
249 *out_dir_index = dir_index;
250 return 0;
251 }
252
253 /**
254 * Get a parameter at |index| as an int.
255 * @param[in] params The parameter array.
256 * @param[in] index The index in |params| to get.
257 * @param[out] out_file The output int32_t.
258 * @param[out] out_error An error message, if this operation failed.
259 * @return int 0 if successful, otherwise 1.
260 */
261 static int GetParamInt(struct PP_Var params,
262 uint32_t index,
263 int32_t* out_int,
264 const char** out_error) {
265 struct PP_Var value = g_ppb_var_array->Get(params, index);
266 if (value.type != PP_VARTYPE_INT32) {
267 *out_error =
268 PrintfToNewString("Expected param at index %d to be an int32", index);
269 return 1;
270 }
271
272 *out_int = value.value.as_int;
273 return 0;
274 }
275
276 /**
277 * Create a response PP_Var to send back to JavaScript.
278 * @param[out] response_var The response PP_Var.
279 * @param[in] cmd The name of the function that is being executed.
280 * @param[out] out_error An error message, if this call failed.
281 */
282 static void CreateResponse(struct PP_Var* response_var,
283 const char* cmd,
284 const char** out_error) {
285 PP_Bool result;
286
287 struct PP_Var dict_var = g_ppb_var_dictionary->Create();
288 struct PP_Var cmd_key = CStrToVar("cmd");
289 struct PP_Var cmd_value = CStrToVar(cmd);
290
291 result = g_ppb_var_dictionary->Set(dict_var, cmd_key, cmd_value);
292 g_ppb_var->Release(cmd_key);
293 g_ppb_var->Release(cmd_value);
294
295 if (!result) {
296 g_ppb_var->Release(dict_var);
297 *out_error =
298 PrintfToNewString("Unable to set \"cmd\" key in result dictionary");
299 return;
300 }
301
302 struct PP_Var args_key = CStrToVar("args");
303 struct PP_Var args_value = g_ppb_var_array->Create();
304 result = g_ppb_var_dictionary->Set(dict_var, args_key, args_value);
305 g_ppb_var->Release(args_key);
306 g_ppb_var->Release(args_value);
307
308 if (!result) {
309 g_ppb_var->Release(dict_var);
310 *out_error =
311 PrintfToNewString("Unable to set \"args\" key in result dictionary");
312 return;
313 }
314
315 *response_var = dict_var;
316 }
317
318 /**
319 * Append a PP_Var to the response dictionary.
320 * @param[in,out] response_var The response PP_var.
321 * @param[in] value The value to add to the response args.
322 * @param[out] out_error An error message, if this call failed.
323 */
324 static void AppendResponseVar(struct PP_Var* response_var,
325 struct PP_Var value,
326 const char** out_error) {
327 struct PP_Var args_value = GetDictVar(*response_var, "args");
328 uint32_t args_length = g_ppb_var_array->GetLength(args_value);
329 PP_Bool result = g_ppb_var_array->Set(args_value, args_length, value);
330 if (!result) {
331 // Release the dictionary that was there before.
332 g_ppb_var->Release(*response_var);
333
334 // Return an error message instead.
335 *response_var = PP_MakeUndefined();
336 *out_error = PrintfToNewString("Unable to append value to result");
337 return;
338 }
339 }
340
341 /**
342 * Append an int to the response dictionary.
343 * @param[in,out] response_var The response PP_var.
344 * @param[in] value The value to add to the response args.
345 * @param[out] out_error An error message, if this call failed.
346 */
347 static void AppendResponseInt(struct PP_Var* response_var,
348 int32_t value,
349 const char** out_error) {
350 AppendResponseVar(response_var, PP_MakeInt32(value), out_error);
351 }
352
353 /**
354 * Append a string to the response dictionary.
355 * @param[in,out] response_var The response PP_var.
356 * @param[in] value The value to add to the response args.
357 * @param[out] out_error An error message, if this call failed.
358 */
359 static void AppendResponseString(struct PP_Var* response_var,
360 const char* value,
361 const char** out_error) {
362 struct PP_Var value_var = CStrToVar(value);
363 AppendResponseVar(response_var, value_var, out_error);
364 g_ppb_var->Release(value_var);
365 }
366
367 #define CHECK_PARAM_COUNT(name, expected) \
368 if (GetNumParams(params) != expected) { \
369 *out_error = PrintfToNewString(#name " takes " #expected " parameters." \
370 " Got %d", GetNumParams(params)); \
371 return 1; \
372 }
373
374 #define PARAM_STRING(index, var) \
375 char* var; \
376 uint32_t var##_len; \
377 if (GetParamString(params, index, &var, &var##_len, out_error)) { \
378 return 1; \
379 }
380
381 #define PARAM_FILE(index, var) \
382 FILE* var; \
383 int32_t var##_index; \
384 if (GetParamFile(params, index, &var, &var##_index, out_error)) { \
385 return 1; \
386 }
387
388 #define PARAM_DIR(index, var) \
389 DIR* var; \
390 int32_t var##_index; \
391 if (GetParamDir(params, index, &var, &var##_index, out_error)) { \
392 return 1; \
393 }
394
395 #define PARAM_INT(index, var) \
396 int32_t var; \
397 if (GetParamInt(params, index, &var, out_error)) { \
398 return 1; \
399 }
400
401 #define CREATE_RESPONSE(name) CreateResponse(output, #name, out_error)
402 #define RESPONSE_STRING(var) AppendResponseString(output, var, out_error)
403 #define RESPONSE_INT(var) AppendResponseInt(output, var, out_error)
404
405 /**
406 * Handle a call to fopen() made by JavaScript.
407 *
408 * fopen expects 2 parameters:
409 * 0: the path of the file to open
410 * 1: the mode string
411 * on success, fopen returns a result in |output|:
412 * 0: "fopen"
413 * 1: the filename opened
414 * 2: the file index
415 * on failure, fopen returns an error string in |out_error|.
416 */
417 int HandleFopen(struct PP_Var params,
418 struct PP_Var* output,
419 const char** out_error) {
420 CHECK_PARAM_COUNT(fopen, 2);
421 PARAM_STRING(0, filename);
422 PARAM_STRING(1, mode);
423
424 FILE* file = fopen(filename, mode);
425
426 if (!file) {
427 *out_error = PrintfToNewString("fopen returned a NULL FILE*");
428 return 1;
429 }
430
431 int file_index = AddFileToMap(file);
432 if (file_index == -1) {
433 *out_error = PrintfToNewString("Example only allows %d open file handles",
434 MAX_OPEN_FILES);
435 return 1;
436 }
437
438 CREATE_RESPONSE(fopen);
439 RESPONSE_STRING(filename);
440 RESPONSE_INT(file_index);
441 return 0;
442 }
443
444 /**
445 * Handle a call to fwrite() made by JavaScript.
446 *
447 * fwrite expects 2 parameters:
448 * 0: The index of the file (which is mapped to a FILE*)
449 * 1: A string to write to the file
450 * on success, fwrite returns a result in |output|:
451 * 0: "fwrite"
452 * 1: the file index
453 * 2: the number of bytes written
454 * on failure, fwrite returns an error string in |out_error|.
455 */
456 int HandleFwrite(struct PP_Var params,
457 struct PP_Var* output,
458 const char** out_error) {
459 CHECK_PARAM_COUNT(fwrite, 2);
460 PARAM_FILE(0, file);
461 PARAM_STRING(1, data);
462
463 size_t bytes_written = fwrite(data, 1, data_len, file);
464 if (ferror(file)) {
465 *out_error = PrintfToNewString("Wrote %d bytes, but ferror() returns true",
466 bytes_written);
467 return 1;
468 }
469
470 CREATE_RESPONSE(fwrite);
471 RESPONSE_INT(file_index);
472 RESPONSE_INT(bytes_written);
473 return 0;
474 }
475
476 /**
477 * Handle a call to fread() made by JavaScript.
478 *
479 * fread expects 2 parameters:
480 * 0: The index of the file (which is mapped to a FILE*)
481 * 1: The number of bytes to read from the file.
482 * on success, fread returns a result in |output|:
483 * 0: "fread"
484 * 1: the file index
485 * 2: the data read from the file
486 * on failure, fread returns an error string in |out_error|.
487 */
488 int HandleFread(struct PP_Var params,
489 struct PP_Var* output,
490 const char** out_error) {
491 CHECK_PARAM_COUNT(fread, 2);
492 PARAM_FILE(0, file);
493 PARAM_INT(1, data_len);
494
495 char* buffer = (char*)malloc(data_len + 1);
496 size_t bytes_read = fread(buffer, 1, data_len, file);
497 buffer[bytes_read] = 0;
498
499 if (ferror(file)) {
500 *out_error = PrintfToNewString("Read %d bytes, but ferror() returns true",
501 bytes_read);
502 free(buffer);
503 return 1;
504 }
505
506 CREATE_RESPONSE(fread);
507 RESPONSE_INT(file_index);
508 RESPONSE_STRING(buffer);
509 free(buffer);
510 return 0;
511 }
512
513 /**
514 * Handle a call to fseek() made by JavaScript.
515 *
516 * fseek expects 3 parameters:
517 * 0: The index of the file (which is mapped to a FILE*)
518 * 1: The offset to seek to
519 * 2: An integer representing the whence parameter of standard fseek.
520 * whence = 0: seek from the beginning of the file
521 * whence = 1: seek from the current file position
522 * whence = 2: seek from the end of the file
523 * on success, fseek returns a result in |output|:
524 * 0: "fseek"
525 * 1: the file index
526 * 2: The new file position
527 * on failure, fseek returns an error string in |out_error|.
528 */
529 int HandleFseek(struct PP_Var params,
530 struct PP_Var* output,
531 const char** out_error) {
532 CHECK_PARAM_COUNT(fseek, 3);
533 PARAM_FILE(0, file);
534 PARAM_INT(1, offset);
535 PARAM_INT(2, whence);
536
537 int result = fseek(file, offset, whence);
538 if (result) {
539 *out_error = PrintfToNewString("fseek returned error %d", result);
540 return 1;
541 }
542
543 offset = ftell(file);
544 if (offset < 0) {
545 *out_error = PrintfToNewString(
546 "fseek succeeded, but ftell returned error %d", offset);
547 return 1;
548 }
549
550 CREATE_RESPONSE(fseek);
551 RESPONSE_INT(file_index);
552 RESPONSE_INT(offset);
553 return 0;
554 }
555
556 /**
557 * Handle a call to fflush() made by JavaScript.
558 *
559 * fflush expects 1 parameters:
560 * 0: The index of the file (which is mapped to a FILE*)
561 * on success, fflush returns a result in |output|:
562 * 0: "fflush"
563 * 1: the file index
564 * on failure, fflush returns an error string in |out_error|.
565 */
566 int HandleFflush(struct PP_Var params,
567 struct PP_Var* output,
568 const char** out_error) {
569 CHECK_PARAM_COUNT(fflush, 1);
570 PARAM_FILE(0, file);
571
572 fflush(file);
573
574 CREATE_RESPONSE(fflush);
575 RESPONSE_INT(file_index);
576 return 0;
577 }
578
579 /**
580 * Handle a call to fclose() made by JavaScript.
581 *
582 * fclose expects 1 parameter:
583 * 0: The index of the file (which is mapped to a FILE*)
584 * on success, fclose returns a result in |output|:
585 * 0: "fclose"
586 * 1: the file index
587 * on failure, fclose returns an error string in |out_error|.
588 */
589 int HandleFclose(struct PP_Var params,
590 struct PP_Var* output,
591 const char** out_error) {
592 CHECK_PARAM_COUNT(fclose, 1);
593 PARAM_FILE(0, file);
594
595 int result = fclose(file);
596 if (result) {
597 *out_error = PrintfToNewString("fclose returned error %d", result);
598 return 1;
599 }
600
601 RemoveFileFromMap(file_index);
602
603 CREATE_RESPONSE(fclose);
604 RESPONSE_INT(file_index);
605 return 0;
606 }
607
608 /**
609 * Handle a call to stat() made by JavaScript.
610 *
611 * stat expects 1 parameter:
612 * 0: The name of the file
613 * on success, stat returns a result in |output|:
614 * 0: "stat"
615 * 1: the file name
616 * 2: the size of the file
617 * on failure, stat returns an error string in |out_error|.
618 */
619 int HandleStat(struct PP_Var params,
620 struct PP_Var* output,
621 const char** out_error) {
622 CHECK_PARAM_COUNT(stat, 1);
623 PARAM_STRING(0, filename);
624
625 struct stat buf;
626 memset(&buf, 0, sizeof(buf));
627 int result = stat(filename, &buf);
628
629 if (result == -1) {
630 *out_error = PrintfToNewString("stat returned error %d", errno);
631 return 1;
632 }
633
634 CREATE_RESPONSE(stat);
635 RESPONSE_STRING(filename);
636 RESPONSE_INT(buf.st_size);
637 return 0;
638 }
639
640 /**
641 * Handle a call to opendir() made by JavaScript.
642 *
643 * opendir expects 1 parameter:
644 * 0: The name of the directory
645 * on success, opendir returns a result in |output|:
646 * 0: "opendir"
647 * 1: the directory name
648 * 2: the index of the directory
649 * on failure, opendir returns an error string in |out_error|.
650 */
651 int HandleOpendir(struct PP_Var params,
652 struct PP_Var* output,
653 const char** out_error) {
654 #if defined(WIN32)
655 *out_error = PrintfToNewString("Win32 does not support opendir");
656 return 1;
657 #else
658 CHECK_PARAM_COUNT(opendir, 1);
659 PARAM_STRING(0, dirname);
660
661 DIR* dir = opendir(dirname);
662
663 if (!dir) {
664 *out_error = PrintfToNewString("opendir returned a NULL DIR*");
665 return 1;
666 }
667
668 int dir_index = AddDirToMap(dir);
669 if (dir_index == -1) {
670 *out_error = PrintfToNewString("Example only allows %d open dir handles",
671 MAX_OPEN_DIRS);
672 return 1;
673 }
674
675 CREATE_RESPONSE(opendir);
676 RESPONSE_STRING(dirname);
677 RESPONSE_INT(dir_index);
678 return 0;
679 #endif
680 }
681
682 /**
683 * Handle a call to readdir() made by JavaScript.
684 *
685 * readdir expects 1 parameter:
686 * 0: The index of the directory (which is mapped to a DIR*)
687 * on success, opendir returns a result in |output|:
688 * 0: "readdir"
689 * 1: the inode number of the entry
690 * 2: the name of the entry
691 * if there are no more entries, |output| contains:
692 * 0: "readdir"
693 * on failure, readdir returns an error string in |out_error|.
694 */
695 int HandleReaddir(struct PP_Var params,
696 struct PP_Var* output,
697 const char** out_error) {
698 #if defined(WIN32)
699 *out_error = PrintfToNewString("Win32 does not support readdir");
700 return 1;
701 #else
702 CHECK_PARAM_COUNT(readdir, 1);
703 PARAM_DIR(0, dir);
704
705 struct dirent* entry = readdir(dir);
706
707 CREATE_RESPONSE(readdir);
708 RESPONSE_INT(dir_index);
709 if (entry != NULL) {
710 RESPONSE_INT(entry->d_ino);
711 RESPONSE_STRING(entry->d_name);
712 }
713 return 0;
714 #endif
715 }
716
717 /**
718 * Handle a call to closedir() made by JavaScript.
719 *
720 * closedir expects 1 parameter:
721 * 0: The index of the directory (which is mapped to a DIR*)
722 * on success, closedir returns a result in |output|:
723 * 0: "closedir"
724 * 1: the name of the directory
725 * on failure, closedir returns an error string in |out_error|.
726 */
727 int HandleClosedir(struct PP_Var params,
728 struct PP_Var* output,
729 const char** out_error) {
730 #if defined(WIN32)
731 *out_error = PrintfToNewString("Win32 does not support closedir");
732 return 1;
733 #else
734 CHECK_PARAM_COUNT(closedir, 1);
735 PARAM_DIR(0, dir);
736
737 int result = closedir(dir);
738 if (result) {
739 *out_error = PrintfToNewString("closedir returned error %d", result);
740 return 1;
741 }
742
743 RemoveDirFromMap(dir_index);
744
745 CREATE_RESPONSE(closedir);
746 RESPONSE_INT(dir_index);
747 return 0;
748 #endif
749 }
750
751 /**
752 * Handle a call to mkdir() made by JavaScript.
753 *
754 * mkdir expects 1 parameter:
755 * 0: The name of the directory
756 * 1: The mode to use for the new directory, in octal.
757 * on success, mkdir returns a result in |output|:
758 * 0: "mkdir"
759 * 1: the name of the directory
760 * on failure, mkdir returns an error string in |out_error|.
761 */
762 int HandleMkdir(struct PP_Var params,
763 struct PP_Var* output,
764 const char** out_error) {
765 CHECK_PARAM_COUNT(mkdir, 2);
766 PARAM_STRING(0, dirname);
767 PARAM_INT(1, mode);
768
769 int result = mkdir(dirname, mode);
770
771 if (result != 0) {
772 *out_error = PrintfToNewString("mkdir returned error: %d", errno);
773 return 1;
774 }
775
776 CREATE_RESPONSE(mkdir);
777 RESPONSE_STRING(dirname);
778 return 0;
779 }
780
781 /**
782 * Handle a call to rmdir() made by JavaScript.
783 *
784 * rmdir expects 1 parameter:
785 * 0: The name of the directory to remove
786 * on success, rmdir returns a result in |output|:
787 * 0: "rmdir"
788 * 1: the name of the directory
789 * on failure, rmdir returns an error string in |out_error|.
790 */
791 int HandleRmdir(struct PP_Var params,
792 struct PP_Var* output,
793 const char** out_error) {
794 CHECK_PARAM_COUNT(rmdir, 1);
795 PARAM_STRING(0, dirname);
796
797 int result = rmdir(dirname);
798
799 if (result != 0) {
800 *out_error = PrintfToNewString("rmdir returned error: %d", errno);
801 return 1;
802 }
803
804 CREATE_RESPONSE(rmdir);
805 RESPONSE_STRING(dirname);
806 return 0;
807 }
808
809 /**
810 * Handle a call to chdir() made by JavaScript.
811 *
812 * chdir expects 1 parameter:
813 * 0: The name of the directory
814 * on success, chdir returns a result in |output|:
815 * 0: "chdir"
816 * 1: the name of the directory
817 * on failure, chdir returns an error string in |out_error|.
818 */
819 int HandleChdir(struct PP_Var params,
820 struct PP_Var* output,
821 const char** out_error) {
822 CHECK_PARAM_COUNT(chdir, 1);
823 PARAM_STRING(0, dirname);
824
825 int result = chdir(dirname);
826
827 if (result != 0) {
828 *out_error = PrintfToNewString("chdir returned error: %d", errno);
829 return 1;
830 }
831
832 CREATE_RESPONSE(chdir);
833 RESPONSE_STRING(dirname);
834 return 0;
835 }
836
837 /**
838 * Handle a call to getcwd() made by JavaScript.
839 *
840 * getcwd expects 0 parameters.
841 * on success, getcwd returns a result in |output|:
842 * 0: "getcwd"
843 * 1: the current working directory
844 * on failure, getcwd returns an error string in |out_error|.
845 */
846 int HandleGetcwd(struct PP_Var params,
847 struct PP_Var* output,
848 const char** out_error) {
849 CHECK_PARAM_COUNT(getcwd, 0);
850
851 char cwd[PATH_MAX];
852 char* result = getcwd(cwd, PATH_MAX);
853 if (result == NULL) {
854 *out_error = PrintfToNewString("getcwd returned error: %d", errno);
855 return 1;
856 }
857
858 CREATE_RESPONSE(getcwd);
859 RESPONSE_STRING(cwd);
860 return 0;
861 }
862
863 /**
864 * Handle a call to getaddrinfo() made by JavaScript.
865 *
866 * getaddrinfo expects 1 parameter:
867 * 0: The name of the host to look up.
868 * on success, getaddrinfo returns a result in |output|:
869 * 0: "getaddrinfo"
870 * 1: The canonical name
871 * 2*n+2: Host name
872 * 2*n+3: Address type (either "AF_INET" or "AF_INET6")
873 * on failure, getaddrinfo returns an error string in |out_error|.
874 */
875 int HandleGetaddrinfo(struct PP_Var params,
876 struct PP_Var* output,
877 const char** out_error) {
878 CHECK_PARAM_COUNT(getaddrinfo, 2);
879 PARAM_STRING(0, name);
880 PARAM_STRING(1, family);
881
882 struct addrinfo hints;
883 memset(&hints, 0, sizeof(hints));
884 hints.ai_flags = AI_CANONNAME;
885 if (!strcmp(family, "AF_INET"))
886 hints.ai_family = AF_INET;
887 else if (!strcmp(family, "AF_INET6"))
888 hints.ai_family = AF_INET6;
889 else if (!strcmp(family, "AF_UNSPEC"))
890 hints.ai_family = AF_UNSPEC;
891 else {
892 *out_error = PrintfToNewString("getaddrinfo uknown family: %s", family);
893 return 1;
894 }
895
896 struct addrinfo* ai;
897 int rtn = getaddrinfo(name, NULL, &hints, &ai);
898 if (rtn != 0) {
899 *out_error = PrintfToNewString("getaddrinfo failed, error is \"%s\"",
900 gai_strerror(rtn));
901 return 2;
902 }
903
904 CREATE_RESPONSE(getaddrinfo);
905 RESPONSE_STRING(ai->ai_canonname);
906 struct addrinfo* current = ai;
907 while (current) {
908 char addr_str[INET6_ADDRSTRLEN];
909 if (ai->ai_family == AF_INET6) {
910 struct sockaddr_in6* in6 = (struct sockaddr_in6*)current->ai_addr;
911 inet_ntop(
912 ai->ai_family, &in6->sin6_addr.s6_addr, addr_str, sizeof(addr_str));
913 } else if (ai->ai_family == AF_INET) {
914 struct sockaddr_in* in = (struct sockaddr_in*)current->ai_addr;
915 inet_ntop(ai->ai_family, &in->sin_addr, addr_str, sizeof(addr_str));
916 }
917
918 RESPONSE_STRING(addr_str);
919 RESPONSE_STRING(ai->ai_family == AF_INET ? "AF_INET" : "AF_INET6");
920
921 current = current->ai_next;
922 }
923
924 freeaddrinfo(ai);
925 return 0;
926 }
927
928 /**
929 * Handle a call to gethostbyname() made by JavaScript.
930 *
931 * gethostbyname expects 1 parameter:
932 * 0: The name of the host to look up.
933 * on success, gethostbyname returns a result in |output|:
934 * 0: "gethostbyname"
935 * 1: Host name
936 * 2: Address type (either "AF_INET" or "AF_INET6")
937 * 3: The first address.
938 * 4+ The second, third, etc. addresses.
939 * on failure, gethostbyname returns an error string in |out_error|.
940 */
941 int HandleGethostbyname(struct PP_Var params,
942 struct PP_Var* output,
943 const char** out_error) {
944 CHECK_PARAM_COUNT(gethostbyname, 1);
945 PARAM_STRING(0, name);
946
947 struct hostent* info = gethostbyname(name);
948 if (!info) {
949 *out_error = PrintfToNewString("gethostbyname failed, error is \"%s\"",
950 hstrerror(h_errno));
951 return 1;
952 }
953
954 CREATE_RESPONSE(gethostbyname);
955 RESPONSE_STRING(info->h_name);
956 RESPONSE_STRING(info->h_addrtype == AF_INET ? "AF_INET" : "AF_INET6");
957
958 struct in_addr** addr_list = (struct in_addr**)info->h_addr_list;
959 int i;
960 for (i = 0; addr_list[i] != NULL; i++) {
961 if (info->h_addrtype == AF_INET) {
962 RESPONSE_STRING(inet_ntoa(*addr_list[i]));
963 } else { // IPv6
964 char addr_str[INET6_ADDRSTRLEN];
965 inet_ntop(AF_INET6, addr_list[i], addr_str, sizeof(addr_str));
966 RESPONSE_STRING(addr_str);
967 }
968 }
969 return 0;
970 }
971
972 /**
973 * Handle a call to connect() made by JavaScript.
974 *
975 * connect expects 2 parameters:
976 * 0: The hostname to connect to.
977 * 1: The port number to connect to.
978 * on success, connect returns a result in |output|:
979 * 0: "connect"
980 * 1: The socket file descriptor.
981 * on failure, connect returns an error string in |out_error|.
982 */
983 int HandleConnect(struct PP_Var params,
984 struct PP_Var* output,
985 const char** out_error) {
986 CHECK_PARAM_COUNT(connect, 2);
987 PARAM_STRING(0, hostname);
988 PARAM_INT(1, port);
989
990 // Lookup host
991 struct hostent* hostent = gethostbyname(hostname);
992 if (hostent == NULL) {
993 *out_error = PrintfToNewString("gethostbyname() returned error: %d", errno);
994 return 1;
995 }
996
997 struct sockaddr_in addr;
998 socklen_t addrlen = sizeof(addr);
999 addr.sin_family = AF_INET;
1000 addr.sin_port = htons(port);
1001 memcpy(&addr.sin_addr.s_addr, hostent->h_addr_list[0], hostent->h_length);
1002
1003 int sock = socket(AF_INET, SOCK_STREAM, 0);
1004 if (sock < 0) {
1005 *out_error = PrintfToNewString("socket() failed: %s", strerror(errno));
1006 return 1;
1007 }
1008
1009 int result = connect(sock, (struct sockaddr*)&addr, addrlen);
1010 if (result != 0) {
1011 *out_error = PrintfToNewString("connect() failed: %s", strerror(errno));
1012 close(sock);
1013 return 1;
1014 }
1015
1016 CREATE_RESPONSE(connect);
1017 RESPONSE_INT(sock);
1018 return 0;
1019 }
1020
1021 /**
1022 * Handle a call to send() made by JavaScript.
1023 *
1024 * send expects 2 parameters:
1025 * 0: The socket file descriptor to send using.
1026 * 1: The NULL terminated string to send.
1027 * on success, send returns a result in |output|:
1028 * 0: "send"
1029 * 1: The number of bytes sent.
1030 * on failure, send returns an error string in |out_error|.
1031 */
1032 int HandleSend(struct PP_Var params,
1033 struct PP_Var* output,
1034 const char** out_error) {
1035 CHECK_PARAM_COUNT(send, 2);
1036 PARAM_INT(0, sock);
1037 PARAM_STRING(1, buffer);
1038
1039 int result = send(sock, buffer, strlen(buffer), 0);
1040 if (result <= 0) {
1041 *out_error = PrintfToNewString("send failed: %s", strerror(errno));
1042 return 1;
1043 }
1044
1045 CREATE_RESPONSE(send);
1046 RESPONSE_INT(result);
1047 return 0;
1048 }
1049
1050 /**
1051 * Handle a call to recv() made by JavaScript.
1052 *
1053 * recv expects 2 parameters:
1054 * 0: The socket file descriptor to recv from.
1055 * 1: The size of the buffer to pass to recv.
1056 * on success, send returns a result in |output|:
1057 * 0: "recv"
1058 * 1: The number of bytes received.
1059 * 2: The data received.
1060 * on failure, recv returns an error string in |out_error|.
1061 */
1062 int HandleRecv(struct PP_Var params,
1063 struct PP_Var* output,
1064 const char** out_error) {
1065 CHECK_PARAM_COUNT(recv, 2);
1066 PARAM_INT(0, sock);
1067 PARAM_INT(1, buffersize);
1068
1069 if (buffersize < 0 || buffersize > 65 * 1024) {
1070 *out_error =
1071 PrintfToNewString("recv buffersize must be between 0 and 65k.");
1072 return 1;
1073 }
1074
1075 char* buffer = alloca(buffersize);
1076 memset(buffer, 0, buffersize);
1077 int result = recv(sock, buffer, buffersize, 0);
1078 if (result <= 0) {
1079 *out_error = PrintfToNewString("recv failed: %s", strerror(errno));
1080 return 1;
1081 }
1082
1083 CREATE_RESPONSE(recv);
1084 RESPONSE_INT(result);
1085 RESPONSE_STRING(buffer);
1086 return 0;
1087 }
1088
1089 /**
1090 * Handle a call to close() made by JavaScript.
1091 *
1092 * close expects 1 parameters:
1093 * 0: The socket file descriptor to close.
1094 * on success, close returns a result in |output|:
1095 * 0: "close"
1096 * 1: The socket file descriptor closed.
1097 * on failure, close returns an error string in |out_error|.
1098 */
1099 int HandleClose(struct PP_Var params,
1100 struct PP_Var* output,
1101 const char** out_error) {
1102 CHECK_PARAM_COUNT(close, 1);
1103 PARAM_INT(0, sock);
1104
1105 int result = close(sock);
1106 if (result != 0) {
1107 *out_error = PrintfToNewString("close returned error: %d", errno);
1108 return 1;
1109 }
1110
1111 CREATE_RESPONSE(close);
1112 RESPONSE_INT(sock);
1113 return 0;
1114 }
OLDNEW
« no previous file with comments | « native_client_sdk/src/examples/demo/nacl_io/handlers.h ('k') | native_client_sdk/src/examples/demo/nacl_io/index.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698