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"
23 #include "nacl_io/osinttypes.h"
25 #include "nacl_io_demo.h"
27 #define MAX_OPEN_FILES 10
28 #define MAX_OPEN_DIRS 10
36 * A mapping from int -> FILE*, so the JavaScript messages can refer to an open
39 static FILE* g_OpenFiles
[MAX_OPEN_FILES
];
42 * A mapping from int -> DIR*, so the JavaScript messages can refer to an open
45 static void* g_OpenDirs
[MAX_OPEN_DIRS
];
48 * A collection of the most recently allocated parameter strings. This makes
49 * the Handle* functions below easier to write because they don't have to
50 * manually deallocate the strings they're using.
52 static char* g_ParamStrings
[MAX_PARAMS
];
55 * Add |object| to |map| and return the index it was added at.
56 * @param[in] map The map to add the object to.
57 * @param[in] max_map_size The maximum map size.
58 * @param[in] object The object to add to the map.
59 * @return int The index of the added object, or -1 if there is no more space.
61 static int AddToMap(void** map
, int max_map_size
, void* object
) {
63 assert(object
!= NULL
);
64 for (i
= 0; i
< max_map_size
; ++i
) {
75 * Remove an object at index |i| from |map|.
76 * @param[in] map The map to remove from.
77 * @param[in] max_map_size The size of the map.
78 * @param[in] i The index to remove.
80 static void RemoveFromMap(void** map
, int max_map_size
, int i
) {
81 assert(i
>= 0 && i
< max_map_size
);
86 * Add the file to the g_OpenFiles map.
87 * @param[in] file The file to add to g_OpenFiles.
88 * @return int The index of the FILE in g_OpenFiles, or -1 if there are too many
91 static int AddFileToMap(FILE* file
) {
92 return AddToMap((void**)g_OpenFiles
, MAX_OPEN_FILES
, file
);
96 * Remove the file from the g_OpenFiles map.
97 * @param[in] i The index of the file handle to remove.
99 static void RemoveFileFromMap(int i
) {
100 RemoveFromMap((void**)g_OpenFiles
, MAX_OPEN_FILES
, i
);
103 /* Win32 doesn't support DIR/opendir/readdir/closedir. */
106 * Add the dir to the g_OpenDirs map.
107 * @param[in] dir The dir to add to g_OpenDirs.
108 * @return int The index of the DIR in g_OpenDirs, or -1 if there are too many
111 static int AddDirToMap(DIR* dir
) {
112 return AddToMap((void**)g_OpenDirs
, MAX_OPEN_DIRS
, dir
);
116 * Remove the dir from the g_OpenDirs map.
117 * @param[in] i The index of the dir handle to remove.
119 static void RemoveDirFromMap(int i
) {
120 RemoveFromMap((void**)g_OpenDirs
, MAX_OPEN_DIRS
, i
);
125 * Get the number of parameters.
126 * @param[in] params The parameter array.
127 * @return uint32_t The number of parameters in the array.
129 static uint32_t GetNumParams(struct PP_Var params
) {
130 return g_ppb_var_array
->GetLength(params
);
134 * Get a parameter at |index| as a string.
135 * @param[in] params The parameter array.
136 * @param[in] index The index in |params| to get.
137 * @param[out] out_string The output string.
138 * @param[out] out_string_len The length of the output string.
139 * @param[out] out_error An error message, if this operation failed.
140 * @return int 0 if successful, otherwise 1.
142 static int GetParamString(struct PP_Var params
,
145 uint32_t* out_string_len
,
146 const char** out_error
) {
147 if (index
>= MAX_PARAMS
) {
148 *out_error
= PrintfToNewString("Param index %u >= MAX_PARAMS (%d)",
153 struct PP_Var value
= g_ppb_var_array
->Get(params
, index
);
154 if (value
.type
!= PP_VARTYPE_STRING
) {
156 PrintfToNewString("Expected param at index %d to be a string", index
);
161 const char* var_str
= g_ppb_var
->VarToUtf8(value
, &length
);
163 char* string
= (char*)malloc(length
+ 1);
164 memcpy(string
, var_str
, length
);
167 /* Put the allocated string in g_ParamStrings. This keeps us from leaking
168 * each parameter string, without having to do manual cleanup in every
169 * Handle* function below.
171 free(g_ParamStrings
[index
]);
172 g_ParamStrings
[index
] = string
;
175 *out_string
= string
;
176 *out_string_len
= length
;
181 * Get a parameter at |index| as a FILE*.
182 * @param[in] params The parameter array.
183 * @param[in] index The index in |params| to get.
184 * @param[out] out_file The output FILE*.
185 * @param[out] out_file_index The index of the output FILE* in g_OpenFiles.
186 * @param[out] out_error An error message, if this operation failed.
187 * @return int 0 if successful, otherwise 1.
189 static int GetParamFile(struct PP_Var params
,
192 int32_t* out_file_index
,
193 const char** out_error
) {
194 struct PP_Var value
= g_ppb_var_array
->Get(params
, index
);
195 if (value
.type
!= PP_VARTYPE_INT32
) {
197 PrintfToNewString("Expected param at index %d to be an int32", index
);
201 int32_t file_index
= value
.value
.as_int
;
202 if (file_index
< 0 || file_index
>= MAX_OPEN_FILES
) {
203 *out_error
= PrintfToNewString("File index %d is out range", file_index
);
207 if (g_OpenFiles
[file_index
] == NULL
) {
208 *out_error
= PrintfToNewString("File index %d is not open", file_index
);
212 *out_file
= g_OpenFiles
[file_index
];
213 *out_file_index
= file_index
;
218 * Get a parameter at |index| as a DIR*.
219 * @param[in] params The parameter array.
220 * @param[in] index The index in |params| to get.
221 * @param[out] out_file The output DIR*.
222 * @param[out] out_file_index The index of the output DIR* in g_OpenDirs.
223 * @param[out] out_error An error message, if this operation failed.
224 * @return int 0 if successful, otherwise 1.
226 static int GetParamDir(struct PP_Var params
,
229 int32_t* out_dir_index
,
230 const char** out_error
) {
231 struct PP_Var value
= g_ppb_var_array
->Get(params
, index
);
232 if (value
.type
!= PP_VARTYPE_INT32
) {
234 PrintfToNewString("Expected param at index %d to be an int32", index
);
238 int32_t dir_index
= value
.value
.as_int
;
239 if (dir_index
< 0 || dir_index
>= MAX_OPEN_DIRS
) {
240 *out_error
= PrintfToNewString("Dir at index %d is out range", dir_index
);
244 if (g_OpenDirs
[dir_index
] == NULL
) {
245 *out_error
= PrintfToNewString("Dir index %d is not open", dir_index
);
249 *out_dir
= g_OpenDirs
[dir_index
];
250 *out_dir_index
= dir_index
;
255 * Get a parameter at |index| as an int.
256 * @param[in] params The parameter array.
257 * @param[in] index The index in |params| to get.
258 * @param[out] out_file The output int32_t.
259 * @param[out] out_error An error message, if this operation failed.
260 * @return int 0 if successful, otherwise 1.
262 static int GetParamInt(struct PP_Var params
,
265 const char** out_error
) {
266 struct PP_Var value
= g_ppb_var_array
->Get(params
, index
);
267 if (value
.type
!= PP_VARTYPE_INT32
) {
269 PrintfToNewString("Expected param at index %d to be an int32", index
);
273 *out_int
= value
.value
.as_int
;
278 * Create a response PP_Var to send back to JavaScript.
279 * @param[out] response_var The response PP_Var.
280 * @param[in] cmd The name of the function that is being executed.
281 * @param[out] out_error An error message, if this call failed.
283 static void CreateResponse(struct PP_Var
* response_var
,
285 const char** out_error
) {
288 struct PP_Var dict_var
= g_ppb_var_dictionary
->Create();
289 struct PP_Var cmd_key
= CStrToVar("cmd");
290 struct PP_Var cmd_value
= CStrToVar(cmd
);
292 result
= g_ppb_var_dictionary
->Set(dict_var
, cmd_key
, cmd_value
);
293 g_ppb_var
->Release(cmd_key
);
294 g_ppb_var
->Release(cmd_value
);
297 g_ppb_var
->Release(dict_var
);
299 PrintfToNewString("Unable to set \"cmd\" key in result dictionary");
303 struct PP_Var args_key
= CStrToVar("args");
304 struct PP_Var args_value
= g_ppb_var_array
->Create();
305 result
= g_ppb_var_dictionary
->Set(dict_var
, args_key
, args_value
);
306 g_ppb_var
->Release(args_key
);
307 g_ppb_var
->Release(args_value
);
310 g_ppb_var
->Release(dict_var
);
312 PrintfToNewString("Unable to set \"args\" key in result dictionary");
316 *response_var
= dict_var
;
320 * Append a PP_Var to the response dictionary.
321 * @param[in,out] response_var The response PP_var.
322 * @param[in] value The value to add to the response args.
323 * @param[out] out_error An error message, if this call failed.
325 static void AppendResponseVar(struct PP_Var
* response_var
,
327 const char** out_error
) {
328 struct PP_Var args_value
= GetDictVar(*response_var
, "args");
329 uint32_t args_length
= g_ppb_var_array
->GetLength(args_value
);
330 PP_Bool result
= g_ppb_var_array
->Set(args_value
, args_length
, value
);
332 // Release the dictionary that was there before.
333 g_ppb_var
->Release(*response_var
);
335 // Return an error message instead.
336 *response_var
= PP_MakeUndefined();
337 *out_error
= PrintfToNewString("Unable to append value to result");
343 * Append an int to the response dictionary.
344 * @param[in,out] response_var The response PP_var.
345 * @param[in] value The value to add to the response args.
346 * @param[out] out_error An error message, if this call failed.
348 static void AppendResponseInt(struct PP_Var
* response_var
,
350 const char** out_error
) {
351 AppendResponseVar(response_var
, PP_MakeInt32(value
), out_error
);
355 * Append a string to the response dictionary.
356 * @param[in,out] response_var The response PP_var.
357 * @param[in] value The value to add to the response args.
358 * @param[out] out_error An error message, if this call failed.
360 static void AppendResponseString(struct PP_Var
* response_var
,
362 const char** out_error
) {
363 struct PP_Var value_var
= CStrToVar(value
);
364 AppendResponseVar(response_var
, value_var
, out_error
);
365 g_ppb_var
->Release(value_var
);
368 #define CHECK_PARAM_COUNT(name, expected) \
369 if (GetNumParams(params) != expected) { \
370 *out_error = PrintfToNewString(#name " takes " #expected " parameters." \
371 " Got %d", GetNumParams(params)); \
375 #define PARAM_STRING(index, var) \
377 uint32_t var##_len; \
378 if (GetParamString(params, index, &var, &var##_len, out_error)) { \
382 #define PARAM_FILE(index, var) \
384 int32_t var##_index; \
385 if (GetParamFile(params, index, &var, &var##_index, out_error)) { \
389 #define PARAM_DIR(index, var) \
391 int32_t var##_index; \
392 if (GetParamDir(params, index, &var, &var##_index, out_error)) { \
396 #define PARAM_INT(index, var) \
398 if (GetParamInt(params, index, &var, out_error)) { \
402 #define CREATE_RESPONSE(name) CreateResponse(output, #name, out_error)
403 #define RESPONSE_STRING(var) AppendResponseString(output, var, out_error)
404 #define RESPONSE_INT(var) AppendResponseInt(output, var, out_error)
407 * Handle a call to fopen() made by JavaScript.
409 * fopen expects 2 parameters:
410 * 0: the path of the file to open
412 * on success, fopen returns a result in |output|:
414 * 1: the filename opened
416 * on failure, fopen returns an error string in |out_error|.
418 int HandleFopen(struct PP_Var params
,
419 struct PP_Var
* output
,
420 const char** out_error
) {
421 CHECK_PARAM_COUNT(fopen
, 2);
422 PARAM_STRING(0, filename
);
423 PARAM_STRING(1, mode
);
425 FILE* file
= fopen(filename
, mode
);
428 *out_error
= PrintfToNewString("fopen returned a NULL FILE*");
432 int file_index
= AddFileToMap(file
);
433 if (file_index
== -1) {
434 *out_error
= PrintfToNewString("Example only allows %d open file handles",
439 CREATE_RESPONSE(fopen
);
440 RESPONSE_STRING(filename
);
441 RESPONSE_INT(file_index
);
446 * Handle a call to fwrite() made by JavaScript.
448 * fwrite expects 2 parameters:
449 * 0: The index of the file (which is mapped to a FILE*)
450 * 1: A string to write to the file
451 * on success, fwrite returns a result in |output|:
454 * 2: the number of bytes written
455 * on failure, fwrite returns an error string in |out_error|.
457 int HandleFwrite(struct PP_Var params
,
458 struct PP_Var
* output
,
459 const char** out_error
) {
460 CHECK_PARAM_COUNT(fwrite
, 2);
462 PARAM_STRING(1, data
);
464 size_t bytes_written
= fwrite(data
, 1, data_len
, file
);
466 *out_error
= PrintfToNewString(
467 "Wrote %" PRIuS
" bytes, but ferror() returns true", bytes_written
);
471 CREATE_RESPONSE(fwrite
);
472 RESPONSE_INT(file_index
);
473 RESPONSE_INT(bytes_written
);
478 * Handle a call to fread() made by JavaScript.
480 * fread expects 2 parameters:
481 * 0: The index of the file (which is mapped to a FILE*)
482 * 1: The number of bytes to read from the file.
483 * on success, fread returns a result in |output|:
486 * 2: the data read from the file
487 * on failure, fread returns an error string in |out_error|.
489 int HandleFread(struct PP_Var params
,
490 struct PP_Var
* output
,
491 const char** out_error
) {
492 CHECK_PARAM_COUNT(fread
, 2);
494 PARAM_INT(1, data_len
);
496 char* buffer
= (char*)malloc(data_len
+ 1);
497 size_t bytes_read
= fread(buffer
, 1, data_len
, file
);
498 buffer
[bytes_read
] = 0;
501 *out_error
= PrintfToNewString(
502 "Read %" PRIuS
" bytes, but ferror() returns true", bytes_read
);
507 CREATE_RESPONSE(fread
);
508 RESPONSE_INT(file_index
);
509 RESPONSE_STRING(buffer
);
515 * Handle a call to fseek() made by JavaScript.
517 * fseek expects 3 parameters:
518 * 0: The index of the file (which is mapped to a FILE*)
519 * 1: The offset to seek to
520 * 2: An integer representing the whence parameter of standard fseek.
521 * whence = 0: seek from the beginning of the file
522 * whence = 1: seek from the current file position
523 * whence = 2: seek from the end of the file
524 * on success, fseek returns a result in |output|:
527 * 2: The new file position
528 * on failure, fseek returns an error string in |out_error|.
530 int HandleFseek(struct PP_Var params
,
531 struct PP_Var
* output
,
532 const char** out_error
) {
533 CHECK_PARAM_COUNT(fseek
, 3);
535 PARAM_INT(1, offset
);
536 PARAM_INT(2, whence
);
538 int result
= fseek(file
, offset
, whence
);
540 *out_error
= PrintfToNewString("fseek returned error %d", result
);
544 offset
= ftell(file
);
546 *out_error
= PrintfToNewString(
547 "fseek succeeded, but ftell returned error %d", offset
);
551 CREATE_RESPONSE(fseek
);
552 RESPONSE_INT(file_index
);
553 RESPONSE_INT(offset
);
558 * Handle a call to fflush() made by JavaScript.
560 * fflush expects 1 parameters:
561 * 0: The index of the file (which is mapped to a FILE*)
562 * on success, fflush returns a result in |output|:
565 * on failure, fflush returns an error string in |out_error|.
567 int HandleFflush(struct PP_Var params
,
568 struct PP_Var
* output
,
569 const char** out_error
) {
570 CHECK_PARAM_COUNT(fflush
, 1);
575 CREATE_RESPONSE(fflush
);
576 RESPONSE_INT(file_index
);
581 * Handle a call to fclose() made by JavaScript.
583 * fclose expects 1 parameter:
584 * 0: The index of the file (which is mapped to a FILE*)
585 * on success, fclose returns a result in |output|:
588 * on failure, fclose returns an error string in |out_error|.
590 int HandleFclose(struct PP_Var params
,
591 struct PP_Var
* output
,
592 const char** out_error
) {
593 CHECK_PARAM_COUNT(fclose
, 1);
596 int result
= fclose(file
);
598 *out_error
= PrintfToNewString("fclose returned error %d", result
);
602 RemoveFileFromMap(file_index
);
604 CREATE_RESPONSE(fclose
);
605 RESPONSE_INT(file_index
);
610 * Handle a call to stat() made by JavaScript.
612 * stat expects 1 parameter:
613 * 0: The name of the file
614 * on success, stat returns a result in |output|:
617 * 2: the size of the file
618 * on failure, stat returns an error string in |out_error|.
620 int HandleStat(struct PP_Var params
,
621 struct PP_Var
* output
,
622 const char** out_error
) {
623 CHECK_PARAM_COUNT(stat
, 1);
624 PARAM_STRING(0, filename
);
627 memset(&buf
, 0, sizeof(buf
));
628 int result
= stat(filename
, &buf
);
631 *out_error
= PrintfToNewString("stat returned error %d", errno
);
635 CREATE_RESPONSE(stat
);
636 RESPONSE_STRING(filename
);
637 RESPONSE_INT(buf
.st_size
);
642 * Handle a call to opendir() made by JavaScript.
644 * opendir expects 1 parameter:
645 * 0: The name of the directory
646 * on success, opendir returns a result in |output|:
648 * 1: the directory name
649 * 2: the index of the directory
650 * on failure, opendir returns an error string in |out_error|.
652 int HandleOpendir(struct PP_Var params
,
653 struct PP_Var
* output
,
654 const char** out_error
) {
656 *out_error
= PrintfToNewString("Win32 does not support opendir");
659 CHECK_PARAM_COUNT(opendir
, 1);
660 PARAM_STRING(0, dirname
);
662 DIR* dir
= opendir(dirname
);
665 *out_error
= PrintfToNewString("opendir returned a NULL DIR*");
669 int dir_index
= AddDirToMap(dir
);
670 if (dir_index
== -1) {
671 *out_error
= PrintfToNewString("Example only allows %d open dir handles",
676 CREATE_RESPONSE(opendir
);
677 RESPONSE_STRING(dirname
);
678 RESPONSE_INT(dir_index
);
684 * Handle a call to readdir() made by JavaScript.
686 * readdir expects 1 parameter:
687 * 0: The index of the directory (which is mapped to a DIR*)
688 * on success, opendir returns a result in |output|:
690 * 1: the inode number of the entry
691 * 2: the name of the entry
692 * if there are no more entries, |output| contains:
694 * on failure, readdir returns an error string in |out_error|.
696 int HandleReaddir(struct PP_Var params
,
697 struct PP_Var
* output
,
698 const char** out_error
) {
700 *out_error
= PrintfToNewString("Win32 does not support readdir");
703 CHECK_PARAM_COUNT(readdir
, 1);
706 struct dirent
* entry
= readdir(dir
);
708 CREATE_RESPONSE(readdir
);
709 RESPONSE_INT(dir_index
);
711 RESPONSE_INT(entry
->d_ino
);
712 RESPONSE_STRING(entry
->d_name
);
719 * Handle a call to closedir() made by JavaScript.
721 * closedir expects 1 parameter:
722 * 0: The index of the directory (which is mapped to a DIR*)
723 * on success, closedir returns a result in |output|:
725 * 1: the name of the directory
726 * on failure, closedir returns an error string in |out_error|.
728 int HandleClosedir(struct PP_Var params
,
729 struct PP_Var
* output
,
730 const char** out_error
) {
732 *out_error
= PrintfToNewString("Win32 does not support closedir");
735 CHECK_PARAM_COUNT(closedir
, 1);
738 int result
= closedir(dir
);
740 *out_error
= PrintfToNewString("closedir returned error %d", result
);
744 RemoveDirFromMap(dir_index
);
746 CREATE_RESPONSE(closedir
);
747 RESPONSE_INT(dir_index
);
753 * Handle a call to mkdir() made by JavaScript.
755 * mkdir expects 1 parameter:
756 * 0: The name of the directory
757 * 1: The mode to use for the new directory, in octal.
758 * on success, mkdir returns a result in |output|:
760 * 1: the name of the directory
761 * on failure, mkdir returns an error string in |out_error|.
763 int HandleMkdir(struct PP_Var params
,
764 struct PP_Var
* output
,
765 const char** out_error
) {
766 CHECK_PARAM_COUNT(mkdir
, 2);
767 PARAM_STRING(0, dirname
);
770 int result
= mkdir(dirname
, mode
);
773 *out_error
= PrintfToNewString("mkdir returned error: %d", errno
);
777 CREATE_RESPONSE(mkdir
);
778 RESPONSE_STRING(dirname
);
783 * Handle a call to rmdir() made by JavaScript.
785 * rmdir expects 1 parameter:
786 * 0: The name of the directory to remove
787 * on success, rmdir returns a result in |output|:
789 * 1: the name of the directory
790 * on failure, rmdir returns an error string in |out_error|.
792 int HandleRmdir(struct PP_Var params
,
793 struct PP_Var
* output
,
794 const char** out_error
) {
795 CHECK_PARAM_COUNT(rmdir
, 1);
796 PARAM_STRING(0, dirname
);
798 int result
= rmdir(dirname
);
801 *out_error
= PrintfToNewString("rmdir returned error: %d", errno
);
805 CREATE_RESPONSE(rmdir
);
806 RESPONSE_STRING(dirname
);
811 * Handle a call to chdir() made by JavaScript.
813 * chdir expects 1 parameter:
814 * 0: The name of the directory
815 * on success, chdir returns a result in |output|:
817 * 1: the name of the directory
818 * on failure, chdir returns an error string in |out_error|.
820 int HandleChdir(struct PP_Var params
,
821 struct PP_Var
* output
,
822 const char** out_error
) {
823 CHECK_PARAM_COUNT(chdir
, 1);
824 PARAM_STRING(0, dirname
);
826 int result
= chdir(dirname
);
829 *out_error
= PrintfToNewString("chdir returned error: %d", errno
);
833 CREATE_RESPONSE(chdir
);
834 RESPONSE_STRING(dirname
);
839 * Handle a call to getcwd() made by JavaScript.
841 * getcwd expects 0 parameters.
842 * on success, getcwd returns a result in |output|:
844 * 1: the current working directory
845 * on failure, getcwd returns an error string in |out_error|.
847 int HandleGetcwd(struct PP_Var params
,
848 struct PP_Var
* output
,
849 const char** out_error
) {
850 CHECK_PARAM_COUNT(getcwd
, 0);
853 char* result
= getcwd(cwd
, PATH_MAX
);
854 if (result
== NULL
) {
855 *out_error
= PrintfToNewString("getcwd returned error: %d", errno
);
859 CREATE_RESPONSE(getcwd
);
860 RESPONSE_STRING(cwd
);
865 * Handle a call to getaddrinfo() made by JavaScript.
867 * getaddrinfo expects 1 parameter:
868 * 0: The name of the host to look up.
869 * on success, getaddrinfo returns a result in |output|:
871 * 1: The canonical name
873 * 2*n+3: Address type (either "AF_INET" or "AF_INET6")
874 * on failure, getaddrinfo returns an error string in |out_error|.
876 int HandleGetaddrinfo(struct PP_Var params
,
877 struct PP_Var
* output
,
878 const char** out_error
) {
879 CHECK_PARAM_COUNT(getaddrinfo
, 2);
880 PARAM_STRING(0, name
);
881 PARAM_STRING(1, family
);
883 struct addrinfo hints
;
884 memset(&hints
, 0, sizeof(hints
));
885 hints
.ai_flags
= AI_CANONNAME
;
886 if (!strcmp(family
, "AF_INET"))
887 hints
.ai_family
= AF_INET
;
888 else if (!strcmp(family
, "AF_INET6"))
889 hints
.ai_family
= AF_INET6
;
890 else if (!strcmp(family
, "AF_UNSPEC"))
891 hints
.ai_family
= AF_UNSPEC
;
893 *out_error
= PrintfToNewString("getaddrinfo uknown family: %s", family
);
898 int rtn
= getaddrinfo(name
, NULL
, &hints
, &ai
);
900 *out_error
= PrintfToNewString("getaddrinfo failed, error is \"%s\"",
905 CREATE_RESPONSE(getaddrinfo
);
906 RESPONSE_STRING(ai
->ai_canonname
);
907 struct addrinfo
* current
= ai
;
909 char addr_str
[INET6_ADDRSTRLEN
];
910 if (ai
->ai_family
== AF_INET6
) {
911 struct sockaddr_in6
* in6
= (struct sockaddr_in6
*)current
->ai_addr
;
913 ai
->ai_family
, &in6
->sin6_addr
.s6_addr
, addr_str
, sizeof(addr_str
));
914 } else if (ai
->ai_family
== AF_INET
) {
915 struct sockaddr_in
* in
= (struct sockaddr_in
*)current
->ai_addr
;
916 inet_ntop(ai
->ai_family
, &in
->sin_addr
, addr_str
, sizeof(addr_str
));
919 RESPONSE_STRING(addr_str
);
920 RESPONSE_STRING(ai
->ai_family
== AF_INET
? "AF_INET" : "AF_INET6");
922 current
= current
->ai_next
;
930 * Handle a call to gethostbyname() made by JavaScript.
932 * gethostbyname expects 1 parameter:
933 * 0: The name of the host to look up.
934 * on success, gethostbyname returns a result in |output|:
937 * 2: Address type (either "AF_INET" or "AF_INET6")
938 * 3: The first address.
939 * 4+ The second, third, etc. addresses.
940 * on failure, gethostbyname returns an error string in |out_error|.
942 int HandleGethostbyname(struct PP_Var params
,
943 struct PP_Var
* output
,
944 const char** out_error
) {
945 CHECK_PARAM_COUNT(gethostbyname
, 1);
946 PARAM_STRING(0, name
);
948 struct hostent
* info
= gethostbyname(name
);
950 *out_error
= PrintfToNewString("gethostbyname failed, error is \"%s\"",
955 CREATE_RESPONSE(gethostbyname
);
956 RESPONSE_STRING(info
->h_name
);
957 RESPONSE_STRING(info
->h_addrtype
== AF_INET
? "AF_INET" : "AF_INET6");
959 struct in_addr
** addr_list
= (struct in_addr
**)info
->h_addr_list
;
961 for (i
= 0; addr_list
[i
] != NULL
; i
++) {
962 if (info
->h_addrtype
== AF_INET
) {
963 RESPONSE_STRING(inet_ntoa(*addr_list
[i
]));
965 char addr_str
[INET6_ADDRSTRLEN
];
966 inet_ntop(AF_INET6
, addr_list
[i
], addr_str
, sizeof(addr_str
));
967 RESPONSE_STRING(addr_str
);
974 * Handle a call to connect() made by JavaScript.
976 * connect expects 2 parameters:
977 * 0: The hostname to connect to.
978 * 1: The port number to connect to.
979 * on success, connect returns a result in |output|:
981 * 1: The socket file descriptor.
982 * on failure, connect returns an error string in |out_error|.
984 int HandleConnect(struct PP_Var params
,
985 struct PP_Var
* output
,
986 const char** out_error
) {
987 CHECK_PARAM_COUNT(connect
, 2);
988 PARAM_STRING(0, hostname
);
992 struct hostent
* hostent
= gethostbyname(hostname
);
993 if (hostent
== NULL
) {
994 *out_error
= PrintfToNewString("gethostbyname() returned error: %d", errno
);
998 struct sockaddr_in addr
;
999 socklen_t addrlen
= sizeof(addr
);
1000 addr
.sin_family
= AF_INET
;
1001 addr
.sin_port
= htons(port
);
1002 memcpy(&addr
.sin_addr
.s_addr
, hostent
->h_addr_list
[0], hostent
->h_length
);
1004 int sock
= socket(AF_INET
, SOCK_STREAM
, 0);
1006 *out_error
= PrintfToNewString("socket() failed: %s", strerror(errno
));
1010 int result
= connect(sock
, (struct sockaddr
*)&addr
, addrlen
);
1012 *out_error
= PrintfToNewString("connect() failed: %s", strerror(errno
));
1017 CREATE_RESPONSE(connect
);
1023 * Handle a call to send() made by JavaScript.
1025 * send expects 2 parameters:
1026 * 0: The socket file descriptor to send using.
1027 * 1: The NULL terminated string to send.
1028 * on success, send returns a result in |output|:
1030 * 1: The number of bytes sent.
1031 * on failure, send returns an error string in |out_error|.
1033 int HandleSend(struct PP_Var params
,
1034 struct PP_Var
* output
,
1035 const char** out_error
) {
1036 CHECK_PARAM_COUNT(send
, 2);
1038 PARAM_STRING(1, buffer
);
1040 int result
= send(sock
, buffer
, strlen(buffer
), 0);
1042 *out_error
= PrintfToNewString("send failed: %s", strerror(errno
));
1046 CREATE_RESPONSE(send
);
1047 RESPONSE_INT(result
);
1052 * Handle a call to recv() made by JavaScript.
1054 * recv expects 2 parameters:
1055 * 0: The socket file descriptor to recv from.
1056 * 1: The size of the buffer to pass to recv.
1057 * on success, send returns a result in |output|:
1059 * 1: The number of bytes received.
1060 * 2: The data received.
1061 * on failure, recv returns an error string in |out_error|.
1063 int HandleRecv(struct PP_Var params
,
1064 struct PP_Var
* output
,
1065 const char** out_error
) {
1066 CHECK_PARAM_COUNT(recv
, 2);
1068 PARAM_INT(1, buffersize
);
1070 if (buffersize
< 0 || buffersize
> 65 * 1024) {
1072 PrintfToNewString("recv buffersize must be between 0 and 65k.");
1076 char* buffer
= alloca(buffersize
);
1077 memset(buffer
, 0, buffersize
);
1078 int result
= recv(sock
, buffer
, buffersize
, 0);
1080 *out_error
= PrintfToNewString("recv failed: %s", strerror(errno
));
1084 CREATE_RESPONSE(recv
);
1085 RESPONSE_INT(result
);
1086 RESPONSE_STRING(buffer
);
1091 * Handle a call to close() made by JavaScript.
1093 * close expects 1 parameters:
1094 * 0: The socket file descriptor to close.
1095 * on success, close returns a result in |output|:
1097 * 1: The socket file descriptor closed.
1098 * on failure, close returns an error string in |out_error|.
1100 int HandleClose(struct PP_Var params
,
1101 struct PP_Var
* output
,
1102 const char** out_error
) {
1103 CHECK_PARAM_COUNT(close
, 1);
1106 int result
= close(sock
);
1108 *out_error
= PrintfToNewString("close returned error: %d", errno
);
1112 CREATE_RESPONSE(close
);