|
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>
|
@@ -2149,6 +2150,70 @@ void SetServers(const FunctionCallbackInfo<Value>& args) {
|
2149 | 2150 | args.GetReturnValue().Set(err);
|
2150 | 2151 | }
|
2151 | 2152 |
|
| 2153 | +void SetLocalAddress(const FunctionCallbackInfo<Value>& args) { |
| 2154 | + Environment* env = Environment::GetCurrent(args); |
| 2155 | + ChannelWrap* channel; |
| 2156 | + ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder()); |
| 2157 | + |
| 2158 | + CHECK_EQ(args.Length(), 2); |
| 2159 | + CHECK(args[0]->IsString()); |
| 2160 | + |
| 2161 | + Isolate* isolate = args.GetIsolate(); |
| 2162 | + node::Utf8Value ip0(isolate, args[0]); |
| 2163 | + |
| 2164 | + unsigned char addr0[sizeof(struct in6_addr)]; |
| 2165 | + unsigned char addr1[sizeof(struct in6_addr)]; |
| 2166 | + int type0 = 0; |
| 2167 | + |
| 2168 | + // This function accepts 2 arguments. The first may be either an IPv4 |
| 2169 | + // address or an IPv6 address. If present, the second argument must be the |
| 2170 | + // other type of address. Otherwise, the unspecified type of IP is set |
| 2171 | + // to 0 (any). |
| 2172 | + |
| 2173 | + if (uv_inet_pton(AF_INET, *ip0, &addr0) == 0) { |
| 2174 | + ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr0)); |
| 2175 | + type0 = 4; |
| 2176 | + } else if (uv_inet_pton(AF_INET6, *ip0, &addr0) == 0) { |
| 2177 | + ares_set_local_ip6(channel->cares_channel(), addr0); |
| 2178 | + type0 = 6; |
| 2179 | + } else { |
| 2180 | + THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address."); |
| 2181 | + return; |
| 2182 | + } |
| 2183 | + |
| 2184 | + if (!args[1]->IsUndefined()) { |
| 2185 | + CHECK(args[1]->IsString()); |
| 2186 | + node::Utf8Value ip1(isolate, args[1]); |
| 2187 | + |
| 2188 | + if (uv_inet_pton(AF_INET, *ip1, &addr1) == 0) { |
| 2189 | + if (type0 == 4) { |
| 2190 | + THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv4 addresses."); |
| 2191 | + return; |
| 2192 | + } else { |
| 2193 | + ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr1)); |
| 2194 | + } |
| 2195 | + } else if (uv_inet_pton(AF_INET6, *ip1, &addr1) == 0) { |
| 2196 | + if (type0 == 6) { |
| 2197 | + THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv6 addresses."); |
| 2198 | + return; |
| 2199 | + } else { |
| 2200 | + ares_set_local_ip6(channel->cares_channel(), addr1); |
| 2201 | + } |
| 2202 | + } else { |
| 2203 | + THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address."); |
| 2204 | + return; |
| 2205 | + } |
| 2206 | + } else { |
| 2207 | + // No second arg specifed |
| 2208 | + if (type0 == 4) { |
| 2209 | + memset(&addr1, 0, sizeof(addr1)); |
| 2210 | + ares_set_local_ip6(channel->cares_channel(), addr1); |
| 2211 | + } else { |
| 2212 | + ares_set_local_ip4(channel->cares_channel(), 0); |
| 2213 | + } |
| 2214 | + } |
| 2215 | +} |
| 2216 | + |
2152 | 2217 | void Cancel(const FunctionCallbackInfo<Value>& args) {
|
2153 | 2218 | ChannelWrap* channel;
|
2154 | 2219 | ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
|
@@ -2250,6 +2315,7 @@ void Initialize(Local<Object> target,
|
2250 | 2315 |
|
2251 | 2316 | env->SetProtoMethodNoSideEffect(channel_wrap, "getServers", GetServers);
|
2252 | 2317 | env->SetProtoMethod(channel_wrap, "setServers", SetServers);
|
| 2318 | + env->SetProtoMethod(channel_wrap, "setLocalAddress", SetLocalAddress); |
2253 | 2319 | env->SetProtoMethod(channel_wrap, "cancel", Cancel);
|
2254 | 2320 |
|
2255 | 2321 | Local<String> channelWrapString =
|
|
0 commit comments