diff --git a/Makefile b/Makefile index 54534c2795..9a41b5ea8d 100644 --- a/Makefile +++ b/Makefile @@ -151,6 +151,7 @@ UVTEST += simple/test-net-keepalive UVTEST += simple/test-net-pingpong UVTEST += simple/test-net-reconnect UVTEST += simple/test-net-remote-address-port +UVTEST += simple/test-net-server-bind UVTEST += simple/test-net-server-max-connections UVTEST += simple/test-net-server-try-ports UVTEST += simple/test-net-stream diff --git a/lib/net_uv.js b/lib/net_uv.js index e7dafc5a7b..87b0affea4 100644 --- a/lib/net_uv.js +++ b/lib/net_uv.js @@ -93,6 +93,11 @@ Socket.prototype.setKeepAlive = function(setting, msecs) { }; +Socket.prototype.address = function() { + return this._handle.getsockname(); +}; + + Object.defineProperty(Socket.prototype, 'readyState', { get: function() { if (this._connecting) { @@ -559,6 +564,9 @@ Server.prototype.listen = function() { } }; +Server.prototype.address = function() { + return this._handle.getsockname(); +}; function onconnection(clientHandle) { var handle = this; diff --git a/src/tcp_wrap.cc b/src/tcp_wrap.cc index 049f91d67b..4a7e1a08e9 100644 --- a/src/tcp_wrap.cc +++ b/src/tcp_wrap.cc @@ -1,6 +1,21 @@ #include #include +// Temporary hack: libuv should provide uv_inet_pton and uv_inet_ntop. +#ifdef __MINGW32__ + extern "C" { +# include +# include + } +# define uv_inet_pton ares_inet_pton +# define uv_inet_ntop ares_inet_ntop + +#else // __POSIX__ +# include +# define uv_inet_pton inet_pton +# define uv_inet_ntop inet_ntop +#endif + #define SLAB_SIZE (1024 * 1024) #define MIN(a, b) ((a) < (b) ? (a) : (b)) @@ -57,6 +72,9 @@ static uv_tcp_t* handle_that_last_alloced; static Persistent slab_sym; static Persistent buffer_sym; +static Persistent family_symbol; +static Persistent address_symbol; +static Persistent port_symbol; static Persistent write_queue_size_sym; class TCPWrap; @@ -113,6 +131,7 @@ class TCPWrap { NODE_SET_PROTOTYPE_METHOD(t, "close", Close); NODE_SET_PROTOTYPE_METHOD(t, "bind6", Bind6); NODE_SET_PROTOTYPE_METHOD(t, "connect6", Connect6); + NODE_SET_PROTOTYPE_METHOD(t, "getsockname", GetSockName); constructor = Persistent::New(t->GetFunction()); @@ -121,6 +140,10 @@ class TCPWrap { write_queue_size_sym = Persistent::New(String::NewSymbol("writeQueueSize")); + family_symbol = NODE_PSYMBOL("family"); + address_symbol = NODE_PSYMBOL("address"); + port_symbol = NODE_PSYMBOL("port"); + target->Set(String::NewSymbol("TCP"), constructor); } @@ -172,6 +195,43 @@ class TCPWrap { object_->Set(write_queue_size_sym, Integer::New(handle_.write_queue_size)); } + static Handle GetSockName(const Arguments& args) { + HandleScope scope; + struct sockaddr address; + int family; + int port; + char ip[INET6_ADDRSTRLEN]; + + UNWRAP + + int namelen = sizeof(address); + int r = uv_getsockname(&wrap->handle_, &address, &namelen); + + Local sockname = Object::New(); + if (r != 0) { + SetErrno(uv_last_error().code); + } else { + family = address.sa_family; + if (family == AF_INET) { + struct sockaddr_in* addrin = (struct sockaddr_in*)&address; + uv_inet_ntop(AF_INET, &(addrin->sin_addr), ip, INET6_ADDRSTRLEN); + port = ntohs(addrin->sin_port); + } else if (family == AF_INET6) { + struct sockaddr_in6* addrin6 = (struct sockaddr_in6*)&address; + uv_inet_ntop(AF_INET6, &(addrin6->sin6_addr), ip, INET6_ADDRSTRLEN); + port = ntohs(addrin6->sin6_port); + } + + sockname->Set(port_symbol, Integer::New(port)); + sockname->Set(family_symbol, Integer::New(family)); + sockname->Set(address_symbol, String::New(ip)); + } + + return scope.Close(sockname); + + } + + static Handle Bind(const Arguments& args) { HandleScope scope;