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. */
12 #include <netinet/in.h>
18 #include <sys/types.h>
19 #include <sys/socket.h>
22 #include "nacl_io/osdirent.h"
24 #include "nacl_io_demo.h"
26 #define MAX_OPEN_FILES 10
27 #define MAX_OPEN_DIRS 10
35 * A mapping from int -> FILE*, so the JavaScript messages can refer to an open
38 static FILE* g_OpenFiles
[MAX_OPEN_FILES
];
41 * A mapping from int -> DIR*, so the JavaScript messages can refer to an open
44 static void* g_OpenDirs
[MAX_OPEN_DIRS
];
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.
51 static char* g_ParamStrings
[MAX_PARAMS
];
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.
60 static int AddToMap(void** map
, int max_map_size
, void* object
) {
62 assert(object
!= NULL
);
63 for (i
= 0; i
< max_map_size
; ++i
) {
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.
79 static void RemoveFromMap(void** map
, int max_map_size
, int i
) {
80 assert(i
>= 0 && i
< max_map_size
);
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
90 static int AddFileToMap(FILE* file
) {
91 return AddToMap((void**)g_OpenFiles
, MAX_OPEN_FILES
, file
);
95 * Remove the file from the g_OpenFiles map.
96 * @param[in] i The index of the file handle to remove.
98 static void RemoveFileFromMap(int i
) {
99 RemoveFromMap((void**)g_OpenFiles
, MAX_OPEN_FILES
, i
);
102 /* Win32 doesn't support DIR/opendir/readdir/closedir. */
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
110 static int AddDirToMap(DIR* dir
) {
111 return AddToMap((void**)g_OpenDirs
, MAX_OPEN_DIRS
, dir
);
115 * Remove the dir from the g_OpenDirs map.
116 * @param[in] i The index of the dir handle to remove.
118 static void RemoveDirFromMap(int i
) {
119 RemoveFromMap((void**)g_OpenDirs
, MAX_OPEN_DIRS
, i
);
124 * Get the number of parameters.
125 * @param[in] params The parameter array.
126 * @return uint32_t The number of parameters in the array.
128 static uint32_t GetNumParams(struct PP_Var params
) {
129 return g_ppb_var_array
->GetLength(params
);
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.
141 static int GetParamString(struct PP_Var params
,
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)",
152 struct PP_Var value
= g_ppb_var_array
->Get(params
, index
);
153 if (value
.type
!= PP_VARTYPE_STRING
) {
155 PrintfToNewString("Expected param at index %d to be a string", index
);
160 const char* var_str
= g_ppb_var
->VarToUtf8(value
, &length
);
162 char* string
= (char*)malloc(length
+ 1);
163 memcpy(string
, var_str
, length
);
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.
170 free(g_ParamStrings
[index
]);
171 g_ParamStrings
[index
] = string
;
174 *out_string
= string
;
175 *out_string_len
= length
;
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.
188 static int GetParamFile(struct PP_Var params
,
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
) {
196 PrintfToNewString("Expected param at index %d to be an int32", index
);
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
);
206 if (g_OpenFiles
[file_index
] == NULL
) {
207 *out_error
= PrintfToNewString("File index %d is not open", file_index
);
211 *out_file
= g_OpenFiles
[file_index
];
212 *out_file_index
= file_index
;
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.
225 static int GetParamDir(struct PP_Var params
,
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
) {
233 PrintfToNewString("Expected param at index %d to be an int32", index
);
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
);
243 if (g_OpenDirs
[dir_index
] == NULL
) {
244 *out_error
= PrintfToNewString("Dir index %d is not open", dir_index
);
248 *out_dir
= g_OpenDirs
[dir_index
];
249 *out_dir_index
= dir_index
;
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.
261 static int GetParamInt(struct PP_Var params
,
264 const char** out_error
) {
265 struct PP_Var value
= g_ppb_var_array
->Get(params
, index
);
266 if (value
.type
!= PP_VARTYPE_INT32
) {
268 PrintfToNewString("Expected param at index %d to be an int32", index
);
272 *out_int
= value
.value
.as_int
;
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.
282 static void CreateResponse(struct PP_Var
* response_var
,
284 const char** out_error
) {
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
);
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
);
296 g_ppb_var
->Release(dict_var
);
298 PrintfToNewString("Unable to set \"cmd\" key in result dictionary");
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
);
309 g_ppb_var
->Release(dict_var
);
311 PrintfToNewString("Unable to set \"args\" key in result dictionary");
315 *response_var
= dict_var
;
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.
324 static void AppendResponseVar(struct PP_Var
* response_var
,
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
);
331 // Release the dictionary that was there before.
332 g_ppb_var
->Release(*response_var
);
334 // Return an error message instead.
335 *response_var
= PP_MakeUndefined();
336 *out_error
= PrintfToNewString("Unable to append value to result");
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.
347 static void AppendResponseInt(struct PP_Var
* response_var
,
349 const char** out_error
) {
350 AppendResponseVar(response_var
, PP_MakeInt32(value
), out_error
);
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.
359 static void AppendResponseString(struct PP_Var
* response_var
,
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
);
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)); \
374 #define PARAM_STRING(index, var) \
376 uint32_t var##_len; \
377 if (GetParamString(params, index, &var, &var##_len, out_error)) { \
381 #define PARAM_FILE(index, var) \
383 int32_t var##_index; \
384 if (GetParamFile(params, index, &var, &var##_index, out_error)) { \
388 #define PARAM_DIR(index, var) \
390 int32_t var##_index; \
391 if (GetParamDir(params, index, &var, &var##_index, out_error)) { \
395 #define PARAM_INT(index, var) \
397 if (GetParamInt(params, index, &var, out_error)) { \
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)
406 * Handle a call to fopen() made by JavaScript.
408 * fopen expects 2 parameters:
409 * 0: the path of the file to open
411 * on success, fopen returns a result in |output|:
413 * 1: the filename opened
415 * on failure, fopen returns an error string in |out_error|.
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
);
424 FILE* file
= fopen(filename
, mode
);
427 *out_error
= PrintfToNewString("fopen returned a NULL FILE*");
431 int file_index
= AddFileToMap(file
);
432 if (file_index
== -1) {
433 *out_error
= PrintfToNewString("Example only allows %d open file handles",
438 CREATE_RESPONSE(fopen
);
439 RESPONSE_STRING(filename
);
440 RESPONSE_INT(file_index
);
445 * Handle a call to fwrite() made by JavaScript.
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|:
453 * 2: the number of bytes written
454 * on failure, fwrite returns an error string in |out_error|.
456 int HandleFwrite(struct PP_Var params
,
457 struct PP_Var
* output
,
458 const char** out_error
) {
459 CHECK_PARAM_COUNT(fwrite
, 2);
461 PARAM_STRING(1, data
);
463 size_t bytes_written
= fwrite(data
, 1, data_len
, file
);
465 *out_error
= PrintfToNewString("Wrote %d bytes, but ferror() returns true",
470 CREATE_RESPONSE(fwrite
);
471 RESPONSE_INT(file_index
);
472 RESPONSE_INT(bytes_written
);
477 * Handle a call to fread() made by JavaScript.
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|:
485 * 2: the data read from the file
486 * on failure, fread returns an error string in |out_error|.
488 int HandleFread(struct PP_Var params
,
489 struct PP_Var
* output
,
490 const char** out_error
) {
491 CHECK_PARAM_COUNT(fread
, 2);
493 PARAM_INT(1, data_len
);
495 char* buffer
= (char*)malloc(data_len
+ 1);
496 size_t bytes_read
= fread(buffer
, 1, data_len
, file
);
497 buffer
[bytes_read
] = 0;
500 *out_error
= PrintfToNewString("Read %d bytes, but ferror() returns true",
506 CREATE_RESPONSE(fread
);
507 RESPONSE_INT(file_index
);
508 RESPONSE_STRING(buffer
);
514 * Handle a call to fseek() made by JavaScript.
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|:
526 * 2: The new file position
527 * on failure, fseek returns an error string in |out_error|.
529 int HandleFseek(struct PP_Var params
,
530 struct PP_Var
* output
,
531 const char** out_error
) {
532 CHECK_PARAM_COUNT(fseek
, 3);
534 PARAM_INT(1, offset
);
535 PARAM_INT(2, whence
);
537 int result
= fseek(file
, offset
, whence
);
539 *out_error
= PrintfToNewString("fseek returned error %d", result
);
543 offset
= ftell(file
);
545 *out_error
= PrintfToNewString(
546 "fseek succeeded, but ftell returned error %d", offset
);
550 CREATE_RESPONSE(fseek
);
551 RESPONSE_INT(file_index
);
552 RESPONSE_INT(offset
);
557 * Handle a call to fflush() made by JavaScript.
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|:
564 * on failure, fflush returns an error string in |out_error|.
566 int HandleFflush(struct PP_Var params
,
567 struct PP_Var
* output
,
568 const char** out_error
) {
569 CHECK_PARAM_COUNT(fflush
, 1);
574 CREATE_RESPONSE(fflush
);
575 RESPONSE_INT(file_index
);
580 * Handle a call to fclose() made by JavaScript.
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|:
587 * on failure, fclose returns an error string in |out_error|.
589 int HandleFclose(struct PP_Var params
,
590 struct PP_Var
* output
,
591 const char** out_error
) {
592 CHECK_PARAM_COUNT(fclose
, 1);
595 int result
= fclose(file
);
597 *out_error
= PrintfToNewString("fclose returned error %d", result
);
601 RemoveFileFromMap(file_index
);
603 CREATE_RESPONSE(fclose
);
604 RESPONSE_INT(file_index
);
609 * Handle a call to stat() made by JavaScript.
611 * stat expects 1 parameter:
612 * 0: The name of the file
613 * on success, stat returns a result in |output|:
616 * 2: the size of the file
617 * on failure, stat returns an error string in |out_error|.
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
);
626 memset(&buf
, 0, sizeof(buf
));
627 int result
= stat(filename
, &buf
);
630 *out_error
= PrintfToNewString("stat returned error %d", errno
);
634 CREATE_RESPONSE(stat
);
635 RESPONSE_STRING(filename
);
636 RESPONSE_INT(buf
.st_size
);
641 * Handle a call to opendir() made by JavaScript.
643 * opendir expects 1 parameter:
644 * 0: The name of the directory
645 * on success, opendir returns a result in |output|:
647 * 1: the directory name
648 * 2: the index of the directory
649 * on failure, opendir returns an error string in |out_error|.
651 int HandleOpendir(struct PP_Var params
,
652 struct PP_Var
* output
,
653 const char** out_error
) {
655 *out_error
= PrintfToNewString("Win32 does not support opendir");
658 CHECK_PARAM_COUNT(opendir
, 1);
659 PARAM_STRING(0, dirname
);
661 DIR* dir
= opendir(dirname
);
664 *out_error
= PrintfToNewString("opendir returned a NULL DIR*");
668 int dir_index
= AddDirToMap(dir
);
669 if (dir_index
== -1) {
670 *out_error
= PrintfToNewString("Example only allows %d open dir handles",
675 CREATE_RESPONSE(opendir
);
676 RESPONSE_STRING(dirname
);
677 RESPONSE_INT(dir_index
);
683 * Handle a call to readdir() made by JavaScript.
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|:
689 * 1: the inode number of the entry
690 * 2: the name of the entry
691 * if there are no more entries, |output| contains:
693 * on failure, readdir returns an error string in |out_error|.
695 int HandleReaddir(struct PP_Var params
,
696 struct PP_Var
* output
,
697 const char** out_error
) {
699 *out_error
= PrintfToNewString("Win32 does not support readdir");
702 CHECK_PARAM_COUNT(readdir
, 1);
705 struct dirent
* entry
= readdir(dir
);
707 CREATE_RESPONSE(readdir
);
708 RESPONSE_INT(dir_index
);
710 RESPONSE_INT(entry
->d_ino
);
711 RESPONSE_STRING(entry
->d_name
);
718 * Handle a call to closedir() made by JavaScript.
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|:
724 * 1: the name of the directory
725 * on failure, closedir returns an error string in |out_error|.
727 int HandleClosedir(struct PP_Var params
,
728 struct PP_Var
* output
,
729 const char** out_error
) {
731 *out_error
= PrintfToNewString("Win32 does not support closedir");
734 CHECK_PARAM_COUNT(closedir
, 1);
737 int result
= closedir(dir
);
739 *out_error
= PrintfToNewString("closedir returned error %d", result
);
743 RemoveDirFromMap(dir_index
);
745 CREATE_RESPONSE(closedir
);
746 RESPONSE_INT(dir_index
);
752 * Handle a call to mkdir() made by JavaScript.
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|:
759 * 1: the name of the directory
760 * on failure, mkdir returns an error string in |out_error|.
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
);
769 int result
= mkdir(dirname
, mode
);
772 *out_error
= PrintfToNewString("mkdir returned error: %d", errno
);
776 CREATE_RESPONSE(mkdir
);
777 RESPONSE_STRING(dirname
);
782 * Handle a call to rmdir() made by JavaScript.
784 * rmdir expects 1 parameter:
785 * 0: The name of the directory to remove
786 * on success, rmdir returns a result in |output|:
788 * 1: the name of the directory
789 * on failure, rmdir returns an error string in |out_error|.
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
);
797 int result
= rmdir(dirname
);
800 *out_error
= PrintfToNewString("rmdir returned error: %d", errno
);
804 CREATE_RESPONSE(rmdir
);
805 RESPONSE_STRING(dirname
);
810 * Handle a call to chdir() made by JavaScript.
812 * chdir expects 1 parameter:
813 * 0: The name of the directory
814 * on success, chdir returns a result in |output|:
816 * 1: the name of the directory
817 * on failure, chdir returns an error string in |out_error|.
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
);
825 int result
= chdir(dirname
);
828 *out_error
= PrintfToNewString("chdir returned error: %d", errno
);
832 CREATE_RESPONSE(chdir
);
833 RESPONSE_STRING(dirname
);
838 * Handle a call to getcwd() made by JavaScript.
840 * getcwd expects 0 parameters.
841 * on success, getcwd returns a result in |output|:
843 * 1: the current working directory
844 * on failure, getcwd returns an error string in |out_error|.
846 int HandleGetcwd(struct PP_Var params
,
847 struct PP_Var
* output
,
848 const char** out_error
) {
849 CHECK_PARAM_COUNT(getcwd
, 0);
852 char* result
= getcwd(cwd
, PATH_MAX
);
853 if (result
== NULL
) {
854 *out_error
= PrintfToNewString("getcwd returned error: %d", errno
);
858 CREATE_RESPONSE(getcwd
);
859 RESPONSE_STRING(cwd
);
864 * Handle a call to getaddrinfo() made by JavaScript.
866 * getaddrinfo expects 1 parameter:
867 * 0: The name of the host to look up.
868 * on success, getaddrinfo returns a result in |output|:
870 * 1: The canonical name
872 * 2*n+3: Address type (either "AF_INET" or "AF_INET6")
873 * on failure, getaddrinfo returns an error string in |out_error|.
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
);
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
;
892 *out_error
= PrintfToNewString("getaddrinfo uknown family: %s", family
);
897 int rtn
= getaddrinfo(name
, NULL
, &hints
, &ai
);
899 *out_error
= PrintfToNewString("getaddrinfo failed, error is \"%s\"",
904 CREATE_RESPONSE(getaddrinfo
);
905 RESPONSE_STRING(ai
->ai_canonname
);
906 struct addrinfo
* current
= ai
;
908 char addr_str
[INET6_ADDRSTRLEN
];
909 if (ai
->ai_family
== AF_INET6
) {
910 struct sockaddr_in6
* in6
= (struct sockaddr_in6
*)current
->ai_addr
;
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
));
918 RESPONSE_STRING(addr_str
);
919 RESPONSE_STRING(ai
->ai_family
== AF_INET
? "AF_INET" : "AF_INET6");
921 current
= current
->ai_next
;
929 * Handle a call to gethostbyname() made by JavaScript.
931 * gethostbyname expects 1 parameter:
932 * 0: The name of the host to look up.
933 * on success, gethostbyname returns a result in |output|:
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|.
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
);
947 struct hostent
* info
= gethostbyname(name
);
949 *out_error
= PrintfToNewString("gethostbyname failed, error is \"%s\"",
954 CREATE_RESPONSE(gethostbyname
);
955 RESPONSE_STRING(info
->h_name
);
956 RESPONSE_STRING(info
->h_addrtype
== AF_INET
? "AF_INET" : "AF_INET6");
958 struct in_addr
** addr_list
= (struct in_addr
**)info
->h_addr_list
;
960 for (i
= 0; addr_list
[i
] != NULL
; i
++) {
961 if (info
->h_addrtype
== AF_INET
) {
962 RESPONSE_STRING(inet_ntoa(*addr_list
[i
]));
964 char addr_str
[INET6_ADDRSTRLEN
];
965 inet_ntop(AF_INET6
, addr_list
[i
], addr_str
, sizeof(addr_str
));
966 RESPONSE_STRING(addr_str
);
973 * Handle a call to connect() made by JavaScript.
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|:
980 * 1: The socket file descriptor.
981 * on failure, connect returns an error string in |out_error|.
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
);
991 struct hostent
* hostent
= gethostbyname(hostname
);
992 if (hostent
== NULL
) {
993 *out_error
= PrintfToNewString("gethostbyname() returned error: %d", errno
);
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
);
1003 int sock
= socket(AF_INET
, SOCK_STREAM
, 0);
1005 *out_error
= PrintfToNewString("socket() failed: %s", strerror(errno
));
1009 int result
= connect(sock
, (struct sockaddr
*)&addr
, addrlen
);
1011 *out_error
= PrintfToNewString("connect() failed: %s", strerror(errno
));
1016 CREATE_RESPONSE(connect
);
1022 * Handle a call to send() made by JavaScript.
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|:
1029 * 1: The number of bytes sent.
1030 * on failure, send returns an error string in |out_error|.
1032 int HandleSend(struct PP_Var params
,
1033 struct PP_Var
* output
,
1034 const char** out_error
) {
1035 CHECK_PARAM_COUNT(send
, 2);
1037 PARAM_STRING(1, buffer
);
1039 int result
= send(sock
, buffer
, strlen(buffer
), 0);
1041 *out_error
= PrintfToNewString("send failed: %s", strerror(errno
));
1045 CREATE_RESPONSE(send
);
1046 RESPONSE_INT(result
);
1051 * Handle a call to recv() made by JavaScript.
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|:
1058 * 1: The number of bytes received.
1059 * 2: The data received.
1060 * on failure, recv returns an error string in |out_error|.
1062 int HandleRecv(struct PP_Var params
,
1063 struct PP_Var
* output
,
1064 const char** out_error
) {
1065 CHECK_PARAM_COUNT(recv
, 2);
1067 PARAM_INT(1, buffersize
);
1069 if (buffersize
< 0 || buffersize
> 65 * 1024) {
1071 PrintfToNewString("recv buffersize must be between 0 and 65k.");
1075 char* buffer
= alloca(buffersize
);
1076 memset(buffer
, 0, buffersize
);
1077 int result
= recv(sock
, buffer
, buffersize
, 0);
1079 *out_error
= PrintfToNewString("recv failed: %s", strerror(errno
));
1083 CREATE_RESPONSE(recv
);
1084 RESPONSE_INT(result
);
1085 RESPONSE_STRING(buffer
);
1090 * Handle a call to close() made by JavaScript.
1092 * close expects 1 parameters:
1093 * 0: The socket file descriptor to close.
1094 * on success, close returns a result in |output|:
1096 * 1: The socket file descriptor closed.
1097 * on failure, close returns an error string in |out_error|.
1099 int HandleClose(struct PP_Var params
,
1100 struct PP_Var
* output
,
1101 const char** out_error
) {
1102 CHECK_PARAM_COUNT(close
, 1);
1105 int result
= close(sock
);
1107 *out_error
= PrintfToNewString("close returned error: %d", errno
);
1111 CREATE_RESPONSE(close
);