| 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 |