OLD | NEW |
1 /* Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 /* Copyright (c) 2016 The Chromium Authors. All rights reserved. |
2 * Use of this source code is governed by a BSD-style license that can be | 2 * Use of this source code is governed by a BSD-style license that can be |
3 * found in the LICENSE file. */ | 3 * found in the LICENSE file. */ |
4 | 4 |
5 #include "handlers.h" | 5 #include "handlers.h" |
6 | 6 |
7 #include <arpa/inet.h> | 7 #include <arpa/inet.h> |
8 #include <assert.h> | 8 #include <assert.h> |
9 #include <errno.h> | 9 #include <errno.h> |
10 #include <limits.h> | 10 #include <limits.h> |
11 #include <netdb.h> | 11 #include <netdb.h> |
12 #include <netinet/in.h> | 12 #include <netinet/in.h> |
13 #include <stdio.h> | 13 #include <stdio.h> |
14 #include <stdlib.h> | 14 #include <stdlib.h> |
15 #include <string.h> | 15 #include <string.h> |
16 #include <unistd.h> | 16 #include <unistd.h> |
17 | 17 |
18 #include <sys/types.h> | 18 #include <sys/types.h> |
19 #include <sys/socket.h> | 19 #include <sys/socket.h> |
20 #include <sys/stat.h> | 20 #include <sys/stat.h> |
21 | 21 |
22 #include "nacl_io/osdirent.h" | 22 #include "nacl_io/osdirent.h" |
23 #include "nacl_io/osinttypes.h" | 23 #include "nacl_io/osinttypes.h" |
24 | 24 |
25 #include "nacl_io_demo.h" | 25 #include "googledrivefs_demo.h" |
26 | 26 |
27 #define MAX_OPEN_FILES 10 | 27 #define MAX_OPEN_FILES 10 |
28 #define MAX_OPEN_DIRS 10 | 28 #define MAX_OPEN_DIRS 10 |
29 #define MAX_PARAMS 4 | 29 #define MAX_PARAMS 4 |
30 | 30 |
31 #if defined(WIN32) | 31 #if defined(WIN32) |
32 #define stat _stat | 32 #define stat _stat |
33 #endif | 33 #endif |
34 | 34 |
35 /** | 35 /** |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 memcpy(string, var_str, length); | 164 memcpy(string, var_str, length); |
165 string[length] = 0; | 165 string[length] = 0; |
166 | 166 |
167 /* Put the allocated string in g_ParamStrings. This keeps us from leaking | 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 | 168 * each parameter string, without having to do manual cleanup in every |
169 * Handle* function below. | 169 * Handle* function below. |
170 */ | 170 */ |
171 free(g_ParamStrings[index]); | 171 free(g_ParamStrings[index]); |
172 g_ParamStrings[index] = string; | 172 g_ParamStrings[index] = string; |
173 | 173 |
174 | |
175 *out_string = string; | 174 *out_string = string; |
176 *out_string_len = length; | 175 *out_string_len = length; |
177 return 0; | 176 return 0; |
178 } | 177 } |
179 | 178 |
180 /** | 179 /** |
181 * Get a parameter at |index| as a FILE*. | 180 * Get a parameter at |index| as a FILE*. |
182 * @param[in] params The parameter array. | 181 * @param[in] params The parameter array. |
183 * @param[in] index The index in |params| to get. | 182 * @param[in] index The index in |params| to get. |
184 * @param[out] out_file The output FILE*. | 183 * @param[out] out_file The output FILE*. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 if (dir_index < 0 || dir_index >= MAX_OPEN_DIRS) { | 238 if (dir_index < 0 || dir_index >= MAX_OPEN_DIRS) { |
240 *out_error = PrintfToNewString("Dir at index %d is out range", dir_index); | 239 *out_error = PrintfToNewString("Dir at index %d is out range", dir_index); |
241 return 1; | 240 return 1; |
242 } | 241 } |
243 | 242 |
244 if (g_OpenDirs[dir_index] == NULL) { | 243 if (g_OpenDirs[dir_index] == NULL) { |
245 *out_error = PrintfToNewString("Dir index %d is not open", dir_index); | 244 *out_error = PrintfToNewString("Dir index %d is not open", dir_index); |
246 return 1; | 245 return 1; |
247 } | 246 } |
248 | 247 |
249 *out_dir = g_OpenDirs[dir_index]; | 248 *out_dir = (DIR *) g_OpenDirs[dir_index]; |
250 *out_dir_index = dir_index; | 249 *out_dir_index = dir_index; |
251 return 0; | 250 return 0; |
252 } | 251 } |
253 | 252 |
254 /** | 253 /** |
255 * Get a parameter at |index| as an int. | 254 * Get a parameter at |index| as an int. |
256 * @param[in] params The parameter array. | 255 * @param[in] params The parameter array. |
257 * @param[in] index The index in |params| to get. | 256 * @param[in] index The index in |params| to get. |
258 * @param[out] out_file The output int32_t. | 257 * @param[out] out_file The output int32_t. |
259 * @param[out] out_error An error message, if this operation failed. | 258 * @param[out] out_error An error message, if this operation failed. |
(...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
854 if (result == NULL) { | 853 if (result == NULL) { |
855 *out_error = PrintfToNewString("getcwd returned error: %d", errno); | 854 *out_error = PrintfToNewString("getcwd returned error: %d", errno); |
856 return 1; | 855 return 1; |
857 } | 856 } |
858 | 857 |
859 CREATE_RESPONSE(getcwd); | 858 CREATE_RESPONSE(getcwd); |
860 RESPONSE_STRING(cwd); | 859 RESPONSE_STRING(cwd); |
861 return 0; | 860 return 0; |
862 } | 861 } |
863 | 862 |
864 /** | |
865 * Handle a call to getaddrinfo() made by JavaScript. | |
866 * | |
867 * getaddrinfo expects 1 parameter: | |
868 * 0: The name of the host to look up. | |
869 * on success, getaddrinfo returns a result in |output|: | |
870 * 0: "getaddrinfo" | |
871 * 1: The canonical name | |
872 * 2*n+2: Host name | |
873 * 2*n+3: Address type (either "AF_INET" or "AF_INET6") | |
874 * on failure, getaddrinfo returns an error string in |out_error|. | |
875 */ | |
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); | |
882 | |
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; | |
892 else { | |
893 *out_error = PrintfToNewString("getaddrinfo uknown family: %s", family); | |
894 return 1; | |
895 } | |
896 | |
897 struct addrinfo* ai; | |
898 int rtn = getaddrinfo(name, NULL, &hints, &ai); | |
899 if (rtn != 0) { | |
900 *out_error = PrintfToNewString("getaddrinfo failed, error is \"%s\"", | |
901 gai_strerror(rtn)); | |
902 return 2; | |
903 } | |
904 | |
905 CREATE_RESPONSE(getaddrinfo); | |
906 RESPONSE_STRING(ai->ai_canonname); | |
907 struct addrinfo* current = ai; | |
908 while (current) { | |
909 char addr_str[INET6_ADDRSTRLEN]; | |
910 if (ai->ai_family == AF_INET6) { | |
911 struct sockaddr_in6* in6 = (struct sockaddr_in6*)current->ai_addr; | |
912 inet_ntop( | |
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)); | |
917 } | |
918 | |
919 RESPONSE_STRING(addr_str); | |
920 RESPONSE_STRING(ai->ai_family == AF_INET ? "AF_INET" : "AF_INET6"); | |
921 | |
922 current = current->ai_next; | |
923 } | |
924 | |
925 freeaddrinfo(ai); | |
926 return 0; | |
927 } | |
928 | |
929 /** | |
930 * Handle a call to gethostbyname() made by JavaScript. | |
931 * | |
932 * gethostbyname expects 1 parameter: | |
933 * 0: The name of the host to look up. | |
934 * on success, gethostbyname returns a result in |output|: | |
935 * 0: "gethostbyname" | |
936 * 1: Host name | |
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|. | |
941 */ | |
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); | |
947 | |
948 struct hostent* info = gethostbyname(name); | |
949 if (!info) { | |
950 *out_error = PrintfToNewString("gethostbyname failed, error is \"%s\"", | |
951 hstrerror(h_errno)); | |
952 return 1; | |
953 } | |
954 | |
955 CREATE_RESPONSE(gethostbyname); | |
956 RESPONSE_STRING(info->h_name); | |
957 RESPONSE_STRING(info->h_addrtype == AF_INET ? "AF_INET" : "AF_INET6"); | |
958 | |
959 struct in_addr** addr_list = (struct in_addr**)info->h_addr_list; | |
960 int i; | |
961 for (i = 0; addr_list[i] != NULL; i++) { | |
962 if (info->h_addrtype == AF_INET) { | |
963 RESPONSE_STRING(inet_ntoa(*addr_list[i])); | |
964 } else { // IPv6 | |
965 char addr_str[INET6_ADDRSTRLEN]; | |
966 inet_ntop(AF_INET6, addr_list[i], addr_str, sizeof(addr_str)); | |
967 RESPONSE_STRING(addr_str); | |
968 } | |
969 } | |
970 return 0; | |
971 } | |
972 | |
973 /** | |
974 * Handle a call to connect() made by JavaScript. | |
975 * | |
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|: | |
980 * 0: "connect" | |
981 * 1: The socket file descriptor. | |
982 * on failure, connect returns an error string in |out_error|. | |
983 */ | |
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); | |
989 PARAM_INT(1, port); | |
990 | |
991 // Lookup host | |
992 struct hostent* hostent = gethostbyname(hostname); | |
993 if (hostent == NULL) { | |
994 *out_error = PrintfToNewString("gethostbyname() returned error: %d", errno); | |
995 return 1; | |
996 } | |
997 | |
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); | |
1003 | |
1004 int sock = socket(AF_INET, SOCK_STREAM, 0); | |
1005 if (sock < 0) { | |
1006 *out_error = PrintfToNewString("socket() failed: %s", strerror(errno)); | |
1007 return 1; | |
1008 } | |
1009 | |
1010 int result = connect(sock, (struct sockaddr*)&addr, addrlen); | |
1011 if (result != 0) { | |
1012 *out_error = PrintfToNewString("connect() failed: %s", strerror(errno)); | |
1013 close(sock); | |
1014 return 1; | |
1015 } | |
1016 | |
1017 CREATE_RESPONSE(connect); | |
1018 RESPONSE_INT(sock); | |
1019 return 0; | |
1020 } | |
1021 | |
1022 /** | |
1023 * Handle a call to send() made by JavaScript. | |
1024 * | |
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|: | |
1029 * 0: "send" | |
1030 * 1: The number of bytes sent. | |
1031 * on failure, send returns an error string in |out_error|. | |
1032 */ | |
1033 int HandleSend(struct PP_Var params, | |
1034 struct PP_Var* output, | |
1035 const char** out_error) { | |
1036 CHECK_PARAM_COUNT(send, 2); | |
1037 PARAM_INT(0, sock); | |
1038 PARAM_STRING(1, buffer); | |
1039 | |
1040 int result = send(sock, buffer, strlen(buffer), 0); | |
1041 if (result <= 0) { | |
1042 *out_error = PrintfToNewString("send failed: %s", strerror(errno)); | |
1043 return 1; | |
1044 } | |
1045 | |
1046 CREATE_RESPONSE(send); | |
1047 RESPONSE_INT(result); | |
1048 return 0; | |
1049 } | |
1050 | |
1051 /** | |
1052 * Handle a call to recv() made by JavaScript. | |
1053 * | |
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|: | |
1058 * 0: "recv" | |
1059 * 1: The number of bytes received. | |
1060 * 2: The data received. | |
1061 * on failure, recv returns an error string in |out_error|. | |
1062 */ | |
1063 int HandleRecv(struct PP_Var params, | |
1064 struct PP_Var* output, | |
1065 const char** out_error) { | |
1066 CHECK_PARAM_COUNT(recv, 2); | |
1067 PARAM_INT(0, sock); | |
1068 PARAM_INT(1, buffersize); | |
1069 | |
1070 if (buffersize < 0 || buffersize > 65 * 1024) { | |
1071 *out_error = | |
1072 PrintfToNewString("recv buffersize must be between 0 and 65k."); | |
1073 return 1; | |
1074 } | |
1075 | |
1076 char* buffer = alloca(buffersize); | |
1077 memset(buffer, 0, buffersize); | |
1078 int result = recv(sock, buffer, buffersize, 0); | |
1079 if (result <= 0) { | |
1080 *out_error = PrintfToNewString("recv failed: %s", strerror(errno)); | |
1081 return 1; | |
1082 } | |
1083 | |
1084 CREATE_RESPONSE(recv); | |
1085 RESPONSE_INT(result); | |
1086 RESPONSE_STRING(buffer); | |
1087 return 0; | |
1088 } | |
1089 | |
1090 /** | |
1091 * Handle a call to close() made by JavaScript. | |
1092 * | |
1093 * close expects 1 parameters: | |
1094 * 0: The socket file descriptor to close. | |
1095 * on success, close returns a result in |output|: | |
1096 * 0: "close" | |
1097 * 1: The socket file descriptor closed. | |
1098 * on failure, close returns an error string in |out_error|. | |
1099 */ | |
1100 int HandleClose(struct PP_Var params, | |
1101 struct PP_Var* output, | |
1102 const char** out_error) { | |
1103 CHECK_PARAM_COUNT(close, 1); | |
1104 PARAM_INT(0, sock); | |
1105 | |
1106 int result = close(sock); | |
1107 if (result != 0) { | |
1108 *out_error = PrintfToNewString("close returned error: %d", errno); | |
1109 return 1; | |
1110 } | |
1111 | |
1112 CREATE_RESPONSE(close); | |
1113 RESPONSE_INT(sock); | |
1114 return 0; | |
1115 } | |
OLD | NEW |