Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

getaddrinfo() implementation

Summary:
Added implementation of getaddrinfo() similar to the python one.

Needed for IPV6

Test Plan:
make fast_tests
Ran the following and compared to python

<?php
var_dump(getaddrinfo('www.python.org';, '80'));

Reviewed By: ps
Reviewers: ps, mwilliams
CC: ps, mwilliams
Revert Plan:
Ok

Tags:

- begin *PUBLIC* platform impact section -
Bugzilla: #
- end platform impact -

Differential Revision: 251204
  • Loading branch information...
commit d960f1f1877ac90d9e81fcf91806051c8e070afb 1 parent 6c59bb6
Scott MacVicar scottmac authored
39 src/idl/socket.idl.php
View
@@ -761,6 +761,45 @@
),
));
+DefineFunction(
+ array(
+ 'name' => "getaddrinfo",
+ 'flags' => HasDocComment,
+ 'return' => array(
+ 'type' => Variant,
+ ),
+ 'args' => array(
+ array(
+ 'name' => "host",
+ 'type' => String,
+ ),
+ array(
+ 'name' => "port",
+ 'type' => String,
+ ),
+ array(
+ 'name' => "family",
+ 'type' => Int32,
+ 'value' => "0",
+ ),
+ array(
+ 'name' => "socktype",
+ 'type' => Int32,
+ 'value' => "0",
+ ),
+ array(
+ 'name' => "protocol",
+ 'type' => Int32,
+ 'value' => "0",
+ ),
+ array(
+ 'name' => "flags",
+ 'type' => Int32,
+ 'value' => "0",
+ ),
+ ),
+ ));
+
///////////////////////////////////////////////////////////////////////////////
// Classes
4 src/runtime/ext/ext.h
View
@@ -52,8 +52,8 @@
#include <runtime/ext/profile/extprofile_math.h>
#include <runtime/ext/profile/extprofile_mb.h>
#include <runtime/ext/profile/extprofile_mcrypt.h>
-#include <runtime/ext/profile/extprofile_memcache.h>
#include <runtime/ext/profile/extprofile_memcached.h>
+#include <runtime/ext/profile/extprofile_memcache.h>
#include <runtime/ext/profile/extprofile_misc.h>
#include <runtime/ext/profile/extprofile_mysql.h>
#include <runtime/ext/profile/extprofile_network.h>
@@ -70,8 +70,8 @@
#include <runtime/ext/profile/extprofile_simplexml.h>
#include <runtime/ext/profile/extprofile_soap.h>
#include <runtime/ext/profile/extprofile_socket.h>
-#include <runtime/ext/profile/extprofile_spl.h>
#include <runtime/ext/profile/extprofile_splfile.h>
+#include <runtime/ext/profile/extprofile_spl.h>
#include <runtime/ext/profile/extprofile_sqlite3.h>
#include <runtime/ext/profile/extprofile_stream.h>
#include <runtime/ext/profile/extprofile_string.h>
91 src/runtime/ext/ext_socket.cpp
View
@@ -1093,5 +1093,96 @@ Variant f_pfsockopen(CStrRef hostname, int port /* = -1 */,
return sockopen_impl(hostname, port, errnum, errstr, timeout, true);
}
+String ipaddr_convert(struct sockaddr *addr, int addrlen) {
+ char buffer[NI_MAXHOST];
+ int error = getnameinfo(addr, addrlen, buffer, sizeof(buffer), NULL, 0, NI_NUMERICHOST);
+
+ if (error) {
+ raise_warning(gai_strerror(error));
+ return "";
+ }
+ return String(buffer, CopyString);
+}
+
+Variant f_getaddrinfo(CStrRef host, CStrRef port, int family /* = 0 */,
+ int socktype /* = 0 */, int protocol /* = 0 */,
+ int flags /* = 0 */) {
+ const char *hptr = NULL, *pptr = NULL;
+ if (!host.empty()) {
+ hptr = host.c_str();
+ }
+ if (!port.empty()) {
+ pptr = port.c_str();
+ }
+
+ struct addrinfo hints, *res;
+ struct addrinfo *res0 = NULL;
+ int error;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = socktype;
+ hints.ai_protocol = protocol;
+ hints.ai_flags = flags;
+ error = getaddrinfo(host, port, &hints, &res0);
+
+ if (error) {
+ raise_warning(gai_strerror(error));
+
+ if (res0) {
+ freeaddrinfo(res0);
+ }
+ return false;
+ }
+
+ Array ret = Array::Create();
+
+ for (res = res0; res; res = res->ai_next) {
+ Array data = Array::Create();
+ Array sockinfo = Array::Create();
+
+ data.set("family", res->ai_family);
+ data.set("socktype", res->ai_socktype);
+ data.set("protocol", res->ai_protocol);
+
+ switch (res->ai_addr->sa_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *a;
+ String buffer = ipaddr_convert(res->ai_addr, sizeof(*a));
+ if (!buffer.empty()) {
+ a = (struct sockaddr_in *)res->ai_addr;
+ sockinfo.set("address", buffer);
+ sockinfo.set("port", ntohs(a->sin_port));
+ }
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *a;
+ String buffer = ipaddr_convert(res->ai_addr, sizeof(*a));
+ if (!buffer.empty()) {
+ a = (struct sockaddr_in6 *)res->ai_addr;
+ sockinfo.set("address", buffer);
+ sockinfo.set("port", ntohs(a->sin6_port));
+ sockinfo.set("flow_info", (int32)a->sin6_flowinfo);
+ sockinfo.set("scope_id", (int32)a->sin6_scope_id);
+ }
+ break;
+ }
+ }
+
+ data.set("sockaddr", (sockinfo.empty() ? NULL : sockinfo));
+
+ ret.append(data);
+ }
+
+ if (res0) {
+ freeaddrinfo(res0);
+ }
+
+ return ret;
+}
+
///////////////////////////////////////////////////////////////////////////////
}
2  src/runtime/ext/ext_socket.h
View
@@ -56,6 +56,8 @@ void f_socket_close(CObjRef socket);
String f_socket_strerror(int errnum);
int f_socket_last_error(CObjRef socket = null_object);
void f_socket_clear_error(CObjRef socket = null_object);
+Variant f_getaddrinfo(CStrRef host, CStrRef port, int family = 0,
+ int socktype = 0, int protocol = 0, int flags = 0);
///////////////////////////////////////////////////////////////////////////////
}
6 src/runtime/ext/profile/extprofile_socket.h
View
@@ -181,6 +181,12 @@ inline void x_socket_clear_error(CObjRef socket = null_object) {
f_socket_clear_error(socket);
}
+inline Variant x_getaddrinfo(CStrRef host, CStrRef port, int family = 0, int socktype = 0, int protocol = 0, int flags = 0) {
+ FUNCTION_INJECTION_BUILTIN(getaddrinfo);
+ TAINT_OBSERVER(TAINT_BIT_NONE, TAINT_BIT_NONE);
+ return f_getaddrinfo(host, port, family, socktype, protocol, flags);
+}
+
///////////////////////////////////////////////////////////////////////////////
}
4 src/system/ext.inc
View
@@ -35,8 +35,8 @@
#include "math.inc"
#include "mb.inc"
#include "mcrypt.inc"
-#include "memcache.inc"
#include "memcached.inc"
+#include "memcache.inc"
#include "misc.inc"
#include "mysql.inc"
#include "network.inc"
@@ -53,8 +53,8 @@
#include "simplexml.inc"
#include "soap.inc"
#include "socket.inc"
-#include "spl.inc"
#include "splfile.inc"
+#include "spl.inc"
#include "sqlite3.inc"
#include "stream.inc"
#include "string.inc"
40 src/system/gen/sys/dynamic_table_func.no.cpp
View
@@ -7446,6 +7446,39 @@ Variant ifa_array_map(void *extra, int count, INVOKE_FEW_ARGS_IMPL_ARGS) {
if (count >= 6) p.append(a5);
return (x_array_map(count, arg0, arg1, p));
}
+Variant i_getaddrinfo(void *extra, CArrRef params) {
+ int count ATTRIBUTE_UNUSED = params.size();
+ if (UNLIKELY(count < 2 || count > 6)) return throw_wrong_arguments("getaddrinfo", count, 2, 6, 1);
+ {
+ ArrayData *ad(params.get());
+ ssize_t pos = ad ? ad->iter_begin() : ArrayData::invalid_index;
+ CVarRef arg0((ad->getValue(pos)));
+ CVarRef arg1((ad->getValue(pos = ad->iter_advance(pos))));
+ if (count <= 2) return (x_getaddrinfo(arg0, arg1));
+ CVarRef arg2((ad->getValue(pos = ad->iter_advance(pos))));
+ if (count <= 3) return (x_getaddrinfo(arg0, arg1, arg2));
+ CVarRef arg3((ad->getValue(pos = ad->iter_advance(pos))));
+ if (count <= 4) return (x_getaddrinfo(arg0, arg1, arg2, arg3));
+ CVarRef arg4((ad->getValue(pos = ad->iter_advance(pos))));
+ if (count <= 5) return (x_getaddrinfo(arg0, arg1, arg2, arg3, arg4));
+ CVarRef arg5((ad->getValue(pos = ad->iter_advance(pos))));
+ return (x_getaddrinfo(arg0, arg1, arg2, arg3, arg4, arg5));
+ }
+}
+Variant ifa_getaddrinfo(void *extra, int count, INVOKE_FEW_ARGS_IMPL_ARGS) {
+ if (UNLIKELY(count < 2)) return throw_wrong_arguments("getaddrinfo", count, 2, 6, 1);
+ CVarRef arg0(a0);
+ CVarRef arg1(a1);
+ if (count <= 2) return (x_getaddrinfo(arg0, arg1));
+ CVarRef arg2(a2);
+ if (count <= 3) return (x_getaddrinfo(arg0, arg1, arg2));
+ CVarRef arg3(a3);
+ if (count <= 4) return (x_getaddrinfo(arg0, arg1, arg2, arg3));
+ CVarRef arg4(a4);
+ if (count <= 5) return (x_getaddrinfo(arg0, arg1, arg2, arg3, arg4));
+ CVarRef arg5(a5);
+ return (x_getaddrinfo(arg0, arg1, arg2, arg3, arg4, arg5));
+}
Variant i_magicksharpenimage(void *extra, CArrRef params) {
int count ATTRIBUTE_UNUSED = params.size();
if (UNLIKELY(count < 3 || count > 4)) return throw_wrong_arguments("magicksharpenimage", count, 3, 4, 1);
@@ -37959,6 +37992,7 @@ CallInfo ci_hphp_splfileobject_ftell((void*)&i_hphp_splfileobject_ftell, (void*)
CallInfo ci_pcntl_wifexited((void*)&i_pcntl_wifexited, (void*)&ifa_pcntl_wifexited, 1, 0, 0x0000000000000000LL);
CallInfo ci_magicksetformat((void*)&i_magicksetformat, (void*)&ifa_magicksetformat, 2, 0, 0x0000000000000000LL);
CallInfo ci_array_map((void*)&i_array_map, (void*)&ifa_array_map, 2, 1, 0x0000000000000000LL);
+CallInfo ci_getaddrinfo((void*)&i_getaddrinfo, (void*)&ifa_getaddrinfo, 6, 0, 0x0000000000000000LL);
CallInfo ci_magicksharpenimage((void*)&i_magicksharpenimage, (void*)&ifa_magicksharpenimage, 4, 0, 0x0000000000000000LL);
CallInfo ci_is_infinite((void*)&i_is_infinite, (void*)&ifa_is_infinite, 1, 0, 0x0000000000000000LL);
CallInfo ci_date_timezone_set((void*)&i_date_timezone_set, (void*)&ifa_date_timezone_set, 2, 0, 0x0000000000000000LL);
@@ -43790,6 +43824,12 @@ bool get_call_info_builtin(const CallInfo *&ci, void *&extra, const char *s, int
return true;
}
break;
+ case 2811:
+ HASH_GUARD(0x12FDE503AB422AFBLL, getaddrinfo) {
+ ci = &ci_getaddrinfo;
+ return true;
+ }
+ break;
case 2815:
HASH_GUARD(0x7833F4C337542AFFLL, openssl_pkey_export) {
ci = &ci_openssl_pkey_export;
1  src/system/socket.inc
View
@@ -27,6 +27,7 @@
"socket_strerror", T(String), S(0), "errnum", T(Int32), NULL, NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/function.socket-strerror.php )\n *\n * socket_strerror() takes as its errno parameter a socket error code as\n * returned by socket_last_error() and returns the corresponding\n * explanatory text.\n *\n * Although the error messages generated by the socket extension are in\n * English, the system messages retrieved with this function will appear\n * depending on the current locale (LC_MESSAGES).\n *\n * @errnum int A valid socket error number, likely produced by\n * socket_last_error().\n *\n * @return string Returns the error message associated with the errno\n * parameter.\n */",
"socket_last_error", T(Int32), S(0), "socket", T(Object), "N;", "null", S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/function.socket-last-error.php )\n *\n * If a socket resource is passed to this function, the last error which\n * occurred on this particular socket is returned. If the socket resource\n * is omitted, the error code of the last failed socket function is\n * returned. The latter is particularly helpful for functions like\n * socket_create() which don't return a socket on failure and\n * socket_select() which can fail for reasons not directly tied to a\n * particular socket. The error code is suitable to be fed to\n * socket_strerror() which returns a string describing the given error\n * code.\n *\n * @socket resource\n * A valid socket resource created with\n * socket_create().\n *\n * @return int This function returns a socket error code.\n */",
"socket_clear_error", T(Void), S(0), "socket", T(Object), "N;", "null", S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/function.socket-clear-error.php\n * )\n *\n * This function clears the error code on the given socket or the global\n * last socket error if no socket is specified.\n *\n * This function allows explicitly resetting the error code value either\n * of a socket or of the extension global last error code. This may be\n * useful to detect within a part of the application if an error occurred\n * or not.\n *\n * @socket resource\n * A valid socket resource created with\n * socket_create().\n *\n * @return mixed No value is returned.\n */",
+"getaddrinfo", T(Variant), S(0), "host", T(String), NULL, NULL, S(0), "port", T(String), NULL, NULL, S(0), "family", T(Int32), "i:0;", "0", S(0), "socktype", T(Int32), "i:0;", "0", S(0), "protocol", T(Int32), "i:0;", "0", S(0), "flags", T(Int32), "i:0;", "0", S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/function.getaddrinfo.php )\n *\n *\n * @host string\n * @port string\n * @family int\n * @socktype int\n * @protocol int\n * @flags int\n *\n * @return mixed\n */",
#elif EXT_TYPE == 1
4 src/test/test_ext.h
View
@@ -50,8 +50,8 @@
#include <test/test_ext_math.h>
#include <test/test_ext_mb.h>
#include <test/test_ext_mcrypt.h>
-#include <test/test_ext_memcache.h>
#include <test/test_ext_memcached.h>
+#include <test/test_ext_memcache.h>
#include <test/test_ext_misc.h>
#include <test/test_ext_mysql.h>
#include <test/test_ext_network.h>
@@ -68,8 +68,8 @@
#include <test/test_ext_simplexml.h>
#include <test/test_ext_soap.h>
#include <test/test_ext_socket.h>
-#include <test/test_ext_spl.h>
#include <test/test_ext_splfile.h>
+#include <test/test_ext_spl.h>
#include <test/test_ext_sqlite3.h>
#include <test/test_ext_stream.h>
#include <test/test_ext_string.h>
4 src/test/test_ext.inc
View
@@ -35,8 +35,8 @@ RUN_TESTSUITE(TestExtMailparse);
RUN_TESTSUITE(TestExtMath);
RUN_TESTSUITE(TestExtMb);
RUN_TESTSUITE(TestExtMcrypt);
-RUN_TESTSUITE(TestExtMemcache);
RUN_TESTSUITE(TestExtMemcached);
+RUN_TESTSUITE(TestExtMemcache);
RUN_TESTSUITE(TestExtMisc);
RUN_TESTSUITE(TestExtMysql);
RUN_TESTSUITE(TestExtNetwork);
@@ -53,8 +53,8 @@ RUN_TESTSUITE(TestExtSession);
RUN_TESTSUITE(TestExtSimplexml);
RUN_TESTSUITE(TestExtSoap);
RUN_TESTSUITE(TestExtSocket);
-RUN_TESTSUITE(TestExtSpl);
RUN_TESTSUITE(TestExtSplfile);
+RUN_TESTSUITE(TestExtSpl);
RUN_TESTSUITE(TestExtSqlite3);
RUN_TESTSUITE(TestExtStream);
RUN_TESTSUITE(TestExtString);
Please sign in to comment.
Something went wrong with that request. Please try again.