How do I make a PHP based UDP log viewer? - php

Ok, so many of you may have heard of games like Garry's Mod or Team Fortress 2. They use a remote RCON logging extension, one I wish to utilize on my website for viewing a live console (and also submitting RCON commands but thats easily done)
Anyway, I have tried searching around to find out the commands I need, but the closest I've found is socket_bind. I tried using this, but the IP of '67.202.70.156' cannot be bound. Here is the error it gives me...
Warning: socket_bind() [function.socket-bind]: unable to bind address [99]: Cannot assign requested address in /home1/rainbowd/public_html/udp.php on line 5
I'm not sure if I'm doing something wrong, but here is my code. I borrowed some code from another stackoverflow question...
<?php
$sourceip = '67.202.70.156';
$port = 27500;
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($sock, $sourceip, 27500) or die('Could not bind to address');
//this is where the reading loop should go.
while(1)
{
echo socket_read($sock,1024);
flush();
ob_flush();
}
socket_close($sock);
?>
Before you comment on how im defining $port but not using $port, thats because I was using $port and then stopped to test something.

You'll need to use socket_connect() and then socket_select() to do it the way you've outlined it so far in your code above. Or you might want to use fsockopen() instead; it might be an easier model to use if it fits the desired use.

Related

Detecting peer disconnect (EOF) with PHP socket module

I'm having a weird issue with PHP's sockets library: I do not seem to be able to detect/distinguish server EOF, and my code is helplessly going into an infinite loop as a result.
Further explanation below; first of all, some context (there's nothing particularly fancy going on here):
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, '127.0.0.1', 8081);
for (;;) {
$read = [$socket];
$except = NULL;
$write = [];
print "Select <";
$n = socket_select($read, $write, $except, NULL);
print ">\n";
if (count($read)) {
print "New data: ";
#socket_recv($socket, $data, 1024, NULL);
$data = socket_read($socket, 1024);
print $data."\n";
}
print "Socket status: ".socket_strerror(socket_last_error())."\n";
}
The above code simply connects to a server and prints what it reads. It's a cut-down version of what I have in the small socket library I'm writing.
For testing, I'm currently using ncat -vvklp 8081 to bind a socket and be a server. With that running, I can fire up the code above and it connects and works - eg, I can type in the ncat window, and PHP receives it. (Sending data from PHP is working too, but I've excluded that code as it's not relevant.)
However, the moment I ^C ncat, the code above enters a hard infinite loop - and PHP says there's no error on the socket.
I am trying to figure out where the button is that whacks PHP upside the head and makes it realize that the peer has disconnected.
socket_get_status() is a great misnomer - it's an alias for stream_get_meta_data(), and it doesn't actually work on sockets!
feof() similarly spouts Warning: feof(): supplied resource is not a valid stream resource.
I can't find a socket_* function for detecting peer EOF.
One of the PHP manual notes for socket_read() initially dissuaded me from using that function so I used socket_recv() instead, but I eventually tried it just in case - but no dice; switching the receive call has no effect.
I have discovered that watching the socket for writing and then attempting to write to it will suddenly make PHP go "oh, wait, right" and start returning Broken pipe - but I'm not interested in writing to the server, I want to read from it!
Finally, regarding the commented part - I would far prefer to use PHP's builtin stream functionality, but the stream_* functions do not provide any means for handling asynchronous connect events (which I want to do, as I'm making multiple connections). I can do stream_socket_client(... STREAM_CLIENT_ASYNC_CONNECT ...) but then cannot find out when the connection has been established (6yo PHP bug #52811).
Okay, I figure I might as well turn the comments above into an answer. All credit goes to Ryan Vincent for helping my thick head figure this out :)
socket_recv will return 0 specifically if the peer has disconnected, or FALSE if any other network error has occurred.
For reference, in C, recv()'s return value is the length of the new data you've just received (which can be 0), or -1 to indicate an error condition (the value of which can be found in errno).
Using 0 to indicate an error condition (and just one arbitrary type of error condition, at that) is not standard and unique to PHP in all the wrong ways. Other network libraries don't work this way.
You need to to handle it like this.
$r = socket_recv($socket, $buf, $len);
if ($r === FALSE) {
// Find out what just happened with socket_last_error()
// (there's a great list of error codes in the comments at
// http://php.net/socket_last_error - considering/researching
// the ramifications of each condition is recommended)
} elseif ($r === 0) {
// The peer closed the connection. You need to handle this
// condition and clean up.
} else {
// You DO have data at this point.
// While unlikely, it's possible the remote peer has
// sent you data of 0 length; remember to use strlen($buf).
}

Use a socket on several pages

I am working on a php application that is sending data through a socket. On my main page I establish the connexion with the client, and I would like to send data from another page of the web app.. but I don't know how to do that.
I am currently trying to use $_SESSION variables [close your eyes this is not pretty]
main page :
$socket = socket_create(AF_INET, SOCK_STREAM, 0);
$result = socket_bind($socket, $host, $port);
$result = socket_listen($socket, 3);
$_SESSION['mySocket'] = socket_accept($socket) ;
socket_read($_SESSION['mySocket'], 1024);
second page :
socket_write($_SESSION['mySocket'], "myText", 6) ;
But it does not work because $_SESSION['mySocket'] is not a ressource anymore on the second page (just 0)... If I use the write command on the main page it works fine, but not on another page. Do you have any idea why ? Is there a cleaner way to do that than using $_SESSION variables (surely there is) ?
EDIT : maybe my real question is : when does a socket connexion close (if I didn't ask for it) ?
Sockets are really only for CLI programming, and there you don't have a $_SESSION object available.
Additionally, it doesn't make sense that you will want to share the socket in the first place, because the socket is a means of IPC. If you pass the socket handle between scripts, then what use is the socket anyway?
If you are trying to communicate between one script and the other, you will want to have the first script listen on a socket (as you did), and then create an infinite loop where the script listens for requests.
In the second script, you connect to the same socket, but don't listen to it.
So I guess what you actually want to do, is to have a third file config.php:
And in both scripts use
You will want to expand this later to make the $host configurable independently, if you want to communicate between computers on a network.
All in all, this is quite advanced programming and you will need to read a lot more about sockets. If I haven't scared you off enough, you could read up on some example code as it is shown in the PHP manual.

How to use winsock in C++ to pass $_get superglobal to a .php on localhost

I am trying to use a c++ script to pass some informations from this script to a local server (localhost) using a socket connection.
As I would like to interact with a DB and I am more comfortable with php, I would like to pass the data through $_GET superglobal sending the complete URL correctly and directly formatted with the $_GET[''] variables (not so much hack issues as I am on a stand alone machine).
I read many posts about using winsock2 for cpp, and I step by step implemented the examples in my cpp program but I am experiencing two troubles:
1) I put in the host structure the localhost through gethostbyname() function. I would like to be sure the ip adress is the correct one, but a printf of a converted-into-char host->h_addr sent me back something not looking like an ip_adress. Do you have any better way to see what host got by this function? Is it safe to use gethostbyname() on localhost?
2) I would like to know how I can correctly write the data to be sent to the server to perform the action on the database as would do the opening of the dedicated php web page. I am interested by the correct result, but would me much more interested by a complete and correct reference (website would be nice, or even book) to know what is the correct syntax for message send to the server on a socket.
Hereafter is my code:
SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct hostent *host;
host = gethostbyname("localhost");
SOCKADDR_IN SockAddr;
SockAddr.sin_port = htons(80);
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
printf("Connecting...\n");
if (connect(Socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0)
{
printf("Could not connect");
system("pause");
return 1;
}
else
{
printf("Connected!\n\n");
}
char url[100] = "GET / HTTP/1.1\r\nHost:localhost/CoffeeTime/remove.php?scard_ID=";
strcat(url, scardid);
strcat(url, "&remove=1\r\nConnection: close\r\n\r\n");
int url_len = strlen(url);
printf((char*)url);
printf("\n");
send(Socket, url, url_len, 0);
closesocket(Socket);
WSACleanup();
As you could see, nothing new under the sun, I took most of this code from someone on stackoverflow.
Thank you!
Facing the huge number of answers :) , I will try to give the best answer I could as I finally succeeded to reach my server through this connection.
The solution is only in the string sent to the server : as I use a XAMPP server I could easily see through Netstat that the connection is OK (gethostbyname works well with "localhost" in arg so no need to use inet_addr with a static localhost ip for people as noob as I am.
Looking at XAMPP apache server log and after opening the adressed php page I've seen at the end of the file the GET string and it is no need to give the /localhost/ before the complete link. Moreover, the GET string ends with HTTP 1.1 instead of starting with it.
Finally, my correct syntax is
char url[100] = "GET /CoffeeTime/remove.php?scard_ID=";
strcat(url, scardid);
strcat(url, "&remove=1\r\n74AD45C8&remove=1 HTTP/1.1 \r\n Connection: close\r\n\r\n");
So no big deal, no huge announcement but it can be interesting for people who use XAMPP to see more useful stuff going with the XAMPP control panel.
Thanks to the guy who downgrade me with no comment by the way :o) .

PHP - Catch timeout exception from ldap_connect()

I've written a little monitoring script in PHP, which should monitor a virtual directory and it's active directories. Everything works fine but when the virtual directory service freezes is my ldap_connect() not able to connect but also doesn't get an error back. So my whole script stands still. I think that the ldap_connect function gets a timeout back (like when you try to ping an IP and it's not reachable).
That's my connect command:
$connection = ldap_connect($hostname, $port) or die("Could not connect to {$hostname});
And I haven't found something in the manual for ldap_connect() (manual) about a timelimit parameter in which you could define how long the function should try to connect until it aborts.
How ever I wasn't quite able to come up with a solution with try and catch or something like this. I also didn't wanted to use the set_time_limit() function because my script needs to be run until the end.
I appreciate every help :)
Thanks and greetings
Tim
http://www.php.net/manual/en/function.ldap-set-option.php
particular the following options :-
LDAP_OPT_NETWORK_TIMEOUT
LDAP_OPT_TIMELIMIT
http://www.php.net/manual/en/function.ldap-set-option.php
try set LDAP_OPT_REFERRALS in 0
If you don't want your PHP program to wait XXX seconds before giving up in a case when one of your corporate DC's have failed,
and since ldap_connect() does not have a mechanism to timeout on a user specified time,
this is my workaround which shows excellent practical results.
function serviceping($host, $port=389, $timeout=1)
{
$op = fsockopen($host, $port, $errno, $errstr, $timeout);
if (!$op) return 0; //DC is N/A
else {
fclose($op); //explicitly close open socket connection
return 1; //DC is up & running, we can safely connect with ldap_connect
}
}
// ##### STATIC DC LIST, if your DNS round robin is not setup
//$dclist = array('10.111.222.111', '10.111.222.100', '10.111.222.200');
// ##### DYNAMIC DC LIST, reverse DNS lookup sorted by round-robin result
$dclist = gethostbynamel('domain.name');
foreach ($dclist as $k => $dc) if (serviceping($dc) == true) break; else $dc = 0;
//after this loop, either there will be at least one DC which is available at present, or $dc would return bool false while the next line stops program from further execution
if (!$dc) exit("NO DOMAIN CONTROLLERS AVAILABLE AT PRESENT, PLEASE TRY AGAIN LATER!"); //user being notified
//now, ldap_connect would certainly connect succesfully to DC tested previously and no timeout will occur
$ldapconn = ldap_connect($dc) or die("DC N/A, PLEASE TRY AGAIN LATER.");
Also with this approach, you get a real nice fail over functionality.
Take for an example a company with a dozen of DC-a distributed along distant places.
This way your PHP program will always have high availability if at least one DC is active at present.
You'll need to use an API that supports time-outs. Connection time-outs are not supported in a native fashion by LDAP (the protocol). The timelimit is a client-requested parameter that refers to how long the directory will spend processing a search request, and is not the same as a "connect time-out".

Writing IRC Services for UnrealIRCD

Well, I've been searching for material for this one, and failed to find anything. I am familiar with the IRC protocol, and I want to write IRC Services for my server (running on UnrealIRCD)
I prefer PHP, as I am most proficient there. Can anyone point me at some good tutorials or even explain here how to start? (I only need the basic protocol/syntax and server settings, I'll do the actual functions and abilities myself (hopefully :P)).
Thanks in advance.
A friend of mine me did this one already for InspIRCd. It never was finished, but the basics were working. We simply connected to the IRC server via a Socket-Connection (fsockopen in the first version, socket_create in the second one).
For communication we implemented an interface to InspIRCd with contained the specific lines as stated in the protocol. These methods could then be called by the core.
Reading uncompiled C source code of the Anope services got me pointed in the right direction, although it's a bit of a trial and error as to where to look inside it. I can't remember since it was quite a while ago when I tried my own PHP services, but if each client the services connects requires a PING/PONG reply to keep the connection alive, then won't PHP kinda fall down? The threading isn't that great, Linux only as far as I can remember.
EDIT: Good Lord, I didn't realize how old this question was. That being said, someone might use it so...answer below.
I've done this in PHP so I can tell you it can be done (source code not released).
That being said, I'll throw a basic core at you here:
$socket = socket_create(AF_INET, SOCK_STREAM, 6);
// Prevent fast reconnects if server down but try to connect every ten seconds.
while ( !socket_connect($socket,ADDRESS,PORT) ) {
sleep(10);
}
// set non blocking to avoid 'waiting' for data
socket_set_nonblock($socket);
// INTENTIONAL INFINITE LOOP
while(1) {
$read = array($socket);
// check if there's anything to read.
$num_changed_sockets = #socket_select($read, null, null, 0, 1);
if ( $num_changed_sockets > '0' ) {
// process the socket data here
processSocket(socket_read($socket,10000,PHP_NORMAL_READ));
}
}
Hope this helps you get started!

Categories