简体   繁体   中英

PHP Profiler - Getting client IP and URL from PHP extension using C++

I have created an php extension in c++ which tracks the call graph of each request.And now , I want to get the Remote ipaddress and URL details for every request. Trying in CentOS 7.5 and PHP 5.6.36 (Thread Safety Disabled) ,when the user gives each request(Browser) arrives, apache will pass control to the PHP module when it is processed into the response phase. PHP_RINIT_FUNCTION() is being called for each and every transaction from Zend engine. I tried to get server name and remote address and their details in PHP_RINIT_FUNCTION(apm) function as following,

zval *args;
char * name = "REMOTE_ADDR";
int len = sizeof("REMOTE_ADDR");
if ( (zend_hash_find(&EG(symbol_table), name,len, (void **) &args) != FAILURE) || PG(http_globals)[TRACK_VARS_SERVER] || zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, name,len, (void **) &args) != FAILURE)
 {
 // success
 //converts args(zval*) to string 
 }
else
{
    //failed
    //can't get REMOTE address
}

Is the above approach correct?? If so, it is getting failed for each requests.. Where am i wrong? What is the alternative if any??

What I have done successfully in the past is to read these values from the $_SERVER superglobal array variable. In order to use $_SERVER (especially from the RINIT context), you have to make sure its auto global callback has been invoked. PHP normally calls this on first userspace access (in other words, PHP lazy-loads the superglobals).

To do this, you look up a zend_auto_global value from the auto_globals hashtable and call the auto global callback. You should always check to make sure $_SERVER is not already loaded beforehand; though in your case you are calling it from RINIT so it is always not going to be loaded.

After calling the auto global callback, you can now access $_SERVER just like any other global variable in the symbol_table hashtable.

Here's an example from an extension of mine called uniauth (see this link for complete context on Github):

/* Make sure $_SERVER is auto loaded already. */
if (!zend_hash_exists(&EG(symbol_table),"_SERVER",8)) {
    if (zend_hash_find(CG(auto_globals),"_SERVER",8,(void**)&auto_global) != FAILURE) {
        auto_global->armed = auto_global->auto_global_callback(auto_global->name,
            auto_global->name_len TSRMLS_CC);
    }
    else {
        zend_throw_exception(NULL,"could not activate _SERVER",0 TSRMLS_CC);
        return 0;
    }
}

In this particular part of the codebase, the extension is generating a redirect URI using information in $_SERVER . Here is the code that shows the usage of the server variables to generate the URI (See this link for complete context on Github):

/* Get information about the protocol, host and port number from the _SERVER
 * superglobal. We use HTTPS, HTTP_HOST and SERVER_PORT keys to resolve the
 * scheme, host and port. I know of no better way to do this unfortunately
 * with the PHP/ZEND API. The sapi globals just don't have what I need.
 */
if (zend_hash_find(&EG(symbol_table),"_SERVER",8,(void**)&arr) == FAILURE) {
    zend_throw_exception(NULL,"no _SERVER superglobal",0 TSRMLS_CC);
    return 0;
}
server = Z_ARRVAL_PP(arr);
if (zend_hash_find(server,"HTTPS",6,(void**)&val) != FAILURE) {
    if (Z_TYPE_PP(val) != IS_STRING || strcmp(Z_STRVAL_PP(val),"off") != 0) {
        https = 1;
    }
}
if (zend_hash_find(server,"HTTP_HOST",10,(void**)&val) != FAILURE
    && Z_TYPE_PP(val) == IS_STRING)
{
    host = Z_STRVAL_PP(val);
}
else {
    zend_throw_exception(NULL,"no HTTP_HOST within _SERVER found",0 TSRMLS_CC);
}

In the comment, I bemoan the fact that there is no way to do this without imitating what you'd do in userspace code. You can access the SAPI globals structure in an extension, but it doesn't have all of the information that my project (and yours) required. See the relevant structures in the PHP headers for more on this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM