|
29 | 29 | #include "req_wrap-inl.h"
|
30 | 30 | #include "util-inl.h"
|
31 | 31 | #include "uv.h"
|
| 32 | +#include "node_errors.h" |
32 | 33 |
|
33 | 34 | #include <cerrno>
|
34 | 35 | #include <cstring>
|
@@ -2227,6 +2228,70 @@ void SetServers(const FunctionCallbackInfo<Value>& args) {
|
2227 | 2228 | args.GetReturnValue().Set(err);
|
2228 | 2229 | }
|
2229 | 2230 |
|
| 2231 | +void SetLocalAddress(const FunctionCallbackInfo<Value>& args) { |
| 2232 | + Environment* env = Environment::GetCurrent(args); |
| 2233 | + ChannelWrap* channel; |
| 2234 | + ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder()); |
| 2235 | + |
| 2236 | + CHECK_EQ(args.Length(), 2); |
| 2237 | + CHECK(args[0]->IsString()); |
| 2238 | + |
| 2239 | + Isolate* isolate = args.GetIsolate(); |
| 2240 | + node::Utf8Value ip0(isolate, args[0]); |
| 2241 | + |
| 2242 | + unsigned char addr0[sizeof(struct in6_addr)]; |
| 2243 | + unsigned char addr1[sizeof(struct in6_addr)]; |
| 2244 | + int type0 = 0; |
| 2245 | + |
| 2246 | + // This function accepts 2 arguments. The first may be either an IPv4 |
| 2247 | + // address or an IPv6 address. If present, the second argument must be the |
| 2248 | + // other type of address. Otherwise, the unspecified type of IP is set |
| 2249 | + // to 0 (any). |
| 2250 | + |
| 2251 | + if (uv_inet_pton(AF_INET, *ip0, &addr0) == 0) { |
| 2252 | + ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr0)); |
| 2253 | + type0 = 4; |
| 2254 | + } else if (uv_inet_pton(AF_INET6, *ip0, &addr0) == 0) { |
| 2255 | + ares_set_local_ip6(channel->cares_channel(), addr0); |
| 2256 | + type0 = 6; |
| 2257 | + } else { |
| 2258 | + THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address."); |
| 2259 | + return; |
| 2260 | + } |
| 2261 | + |
| 2262 | + if (!args[1]->IsUndefined()) { |
| 2263 | + CHECK(args[1]->IsString()); |
| 2264 | + node::Utf8Value ip1(isolate, args[1]); |
| 2265 | + |
| 2266 | + if (uv_inet_pton(AF_INET, *ip1, &addr1) == 0) { |
| 2267 | + if (type0 == 4) { |
| 2268 | + THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv4 addresses."); |
| 2269 | + return; |
| 2270 | + } else { |
| 2271 | + ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr1)); |
| 2272 | + } |
| 2273 | + } else if (uv_inet_pton(AF_INET6, *ip1, &addr1) == 0) { |
| 2274 | + if (type0 == 6) { |
| 2275 | + THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv6 addresses."); |
| 2276 | + return; |
| 2277 | + } else { |
| 2278 | + ares_set_local_ip6(channel->cares_channel(), addr1); |
| 2279 | + } |
| 2280 | + } else { |
| 2281 | + THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address."); |
| 2282 | + return; |
| 2283 | + } |
| 2284 | + } else { |
| 2285 | + // No second arg specifed |
| 2286 | + if (type0 == 4) { |
| 2287 | + memset(&addr1, 0, sizeof(addr1)); |
| 2288 | + ares_set_local_ip6(channel->cares_channel(), addr1); |
| 2289 | + } else { |
| 2290 | + ares_set_local_ip4(channel->cares_channel(), 0); |
| 2291 | + } |
| 2292 | + } |
| 2293 | +} |
| 2294 | + |
2230 | 2295 | void Cancel(const FunctionCallbackInfo<Value>& args) {
|
2231 | 2296 | ChannelWrap* channel;
|
2232 | 2297 | ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
|
@@ -2329,6 +2394,7 @@ void Initialize(Local<Object> target,
|
2329 | 2394 |
|
2330 | 2395 | env->SetProtoMethodNoSideEffect(channel_wrap, "getServers", GetServers);
|
2331 | 2396 | env->SetProtoMethod(channel_wrap, "setServers", SetServers);
|
| 2397 | + env->SetProtoMethod(channel_wrap, "setLocalAddress", SetLocalAddress); |
2332 | 2398 | env->SetProtoMethod(channel_wrap, "cancel", Cancel);
|
2333 | 2399 |
|
2334 | 2400 | Local<String> channelWrapString =
|
|
0 commit comments