[PHP] Irc-bot DCC Send probleem

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Peter
  • Registratie: Januari 2005
  • Laatst online: 13-09 17:10
avond :)

Ik zit met een probleem bij een IRC bot die ik aan het maken ben. Ik weet dat PHP hier niet de ideale taal voor is, maar die discussie is zonder twijfel al vaak genoeg gehouden.

Het probleem is dat er een time out komt nadat de eerste 80kb verstuurd is. Bij een bestand, ongeacht de grootte, worden de eerste 80kb perfect verstuurd en opgeslagen, maar verder weigert hij ook maar een byte te ontvangen. Ik heb al verschillende dingen geprobeerd, in het voorbeeld staan 2 hoofd-probeersels (via fsockopen en via sockets, beide hetzelfde probleem).

De code van het deel dat de bestanden ontvangt is:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<?php
// recv.php
set_time_limit( 0 );

function di( $txt ){
    
    $fp = fopen( "/home/admin/__bot/log.txt", "a" );
    fwrite( $fp, $txt."\n" );
    fclose( $fp );
    
    die();
    
    }

$data = file_get_contents( "/home/admin/__bot/data/recv.rsc" );
list( $ip, $port, $file, $user, $size ) = explode( "[||]", $data );

$errno = $errstr = "";
#$fp = fsockopen( $ip, $port, $errno, $errstr, 30 );

if( $fp === false ){
    
#   di( "niet gelukt" );
    
    }

$type = 2;

if( $type == 1 ){

    $sock = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
    
    socket_set_option(
    
        $sock,
        SOL_SOCKET,  // socket level
        SO_SNDTIMEO, // timeout option
        array(
        
            "sec"=>10, // Timeout in seconds
            "usec"=>0  // I assume timeout in microseconds
            
            )
            
        );
    
    socket_connect( $sock, $ip, $port );
    
    $fn = fopen( "/home/admin/__bot/data/files/" . $user . "_" . $file, "w" );
    
    $file = "";
    while(@socket_recv($sock, $data, 128, 0)){
        
        #$data = "";
        #socket_recv( $sock, $data, 128, 0 );
        $file .= $data;//@socket_read( $sock, 128 );
        
        }
    
    fwrite( $fn, $file );
    
    echo socket_strerror( socket_last_error($sock) );
    
    fclose( $fn );
    socket_close( $sock );
    
    }

else{
    
    $sock = fsockopen( $ip, $port, $errno, $errstr, 10 );
    $fn = fopen( "/home/admin/__bot/data/files/" . $user . "_" . $file, "w" );
    
    $loop = 0;
    $data = "";
    
    while (!feof($sock)) {

        $data .= fgets( $sock, 128 );

        }
    
    fwrite( $fn, $data );
    
    fclose( $fn );
    fclose( $sock );
    
    }

unlink( "/home/admin/__bot/data/recv.rsc" );
?>


De code van recv.rsc (waarin gegevens van de host staan): (ip is verwijderd)

code:
1
x.x.x.x[||]1024[||]Kyle.mp3[||]Peter[||]802449


Errors en/of foutmeldingen komen er niet, return van de socket is 'Succes', maar de rest van de bestanden verdwijnen gewoon..

Alvast bedankt!

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

PHP:
52
    while(@socket_recv($sock, $data, 128, 0)){
Haal dat apenstaartje eens weg en kijk dan nog eens of er foutmeldingen komen. ;)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Peter
  • Registratie: Januari 2005
  • Laatst online: 13-09 17:10
-NMe- schreef op zaterdag 11 juni 2005 @ 22:40:
[...]

Haal dat apenstaartje eens weg en kijk dan nog eens of er foutmeldingen komen. ;)
niets...

Acties:
  • 0 Henk 'm!

  • Sybr_E-N
  • Registratie: December 2001
  • Laatst online: 21-09 12:54
Hoe debug jij dan?

Heb je de standaard dingen zoals error level wel hoog genoeg, maw onderdruk je geen foutmeldingen. Door helemaal boven aan in je script error_reporting(E_ALL) te zetten. Maar wat lukt er voor de rest niet, en wat je heb je allemaal al geprobeerd. Ik kan me voorstellen dat je je probleem wat meer moet centraliseren, want 100 regels source gaat wat ver. Probeer eens door te debuggen waar het nou exact fout gaat en probeer met de resultaten daarvan de oorzaak op te sporen.

Acties:
  • 0 Henk 'm!

  • Peter
  • Registratie: Januari 2005
  • Laatst online: 13-09 17:10
Sybr_E-N schreef op zondag 12 juni 2005 @ 00:18:
Hoe debug jij dan?

Heb je de standaard dingen zoals error level wel hoog genoeg, maw onderdruk je geen foutmeldingen. Door helemaal boven aan in je script error_reporting(E_ALL) te zetten. Maar wat lukt er voor de rest niet, en wat je heb je allemaal al geprobeerd. Ik kan me voorstellen dat je je probleem wat meer moet centraliseren, want 100 regels source gaat wat ver. Probeer eens door te debuggen waar het nou exact fout gaat en probeer met de resultaten daarvan de oorzaak op te sporen.
Het gaat dus fout op het moment van verzenden. Het accepteren en openen van een socket met de cliënt gaat prima, de eerste delen van het bestand ophalen werkt, maar als hij een bepaald deel gedaan heeft (per grootte verschillend, bij bestanden van 150kb download hij 80kb, bij bestanden van 2kb download hij 1,9kb), stopt hij met downloaden en komt er een 'timeout'. Errors teruggeven doet hij niet (in enkele gevallen 'timeout'), ik kan geen logische verklaring bedenken waarom de verbinding plotseling zou time-outen. In de source heb ik al gekeken of er niet een of ander command word verstuurd waarop gereageerd moet worden, wat niet het geval is.

Ook met error_reporting op E_ALL heb ik al getest, geen enkele error. Verder heb ik veel getest met socket_read, alles met filepointers te doen (waar hij exact dezelfde resultaten geeft als bij de socket functies), de buffer-groottes te veranderen, net zolang op te gaan halen tot het hele bestand gedownload is ( while( strlen( $data ) < $size ) , waarbij size eerder word door IRC ), wat een eindeloze loop creëert, verschillende soorten connecties te simuleren, ontvangst buffer / timeout buffer van de socket-functies instellingen veranderd, alles gewoon op het scherm laten weergeven (wat hetzelfde resultaat geeft), ik heb geen idee meer.

Alles draait op fedora core 3 en php 4.3.10..

Dan hierbij nog een meer selectiever stukje code,

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$fn = fopen( "/home/admin/nishino/data/files/" . $user . "_" . $file, "w" );

$file = $data = "";
while( socket_recv($sock, $data, 128, 0) ){
    
    #$data = "";
    #socket_recv( $sock, $data, 128, 0 );
    $file .= $data;
    
    }

fwrite( $fn, $file );

fclose( $fn );
socket_close( $sock );

Acties:
  • 0 Henk 'm!

  • Radiant
  • Registratie: Juli 2003
  • Niet online

Radiant

Certified MS Bob Administrator

Je acknowledged de dcc packets niet..
code:
1
2
3
4
5
6
7
8
9
10
11
12
FILE    Data is sent in packets, rather than dumped in a stream manner.
    This allows the DCC SEND connection to survive where an FTP
    connection might fail. The size of the packets is up to the
    client, and may be set by the user. Smaller packets result
    in a higher probability of survival over bad links.
    The recipient should acknowledge each packet by transmitting
    the total number of bytes received as an unsigned, 4 byte
    integer in network byte order. The sender should not continue
    to transmit until the recipient has acknowledged all data
    already transmitted. Additionally, the sender should not
    close the connection until the last byte has been
    acknowledged by the recipient.


http://www.irchelp.org/irchelp/rfc/dccspec.html

Acties:
  • 0 Henk 'm!

  • Peter
  • Registratie: Januari 2005
  • Laatst online: 13-09 17:10
Radiant schreef op zondag 12 juni 2005 @ 00:42:
Je acknowledged de dcc packets niet..
code:
1
2
3
4
5
6
7
8
9
10
11
12
FILE    Data is sent in packets, rather than dumped in a stream manner.
    This allows the DCC SEND connection to survive where an FTP
    connection might fail. The size of the packets is up to the
    client, and may be set by the user. Smaller packets result
    in a higher probability of survival over bad links.
    The recipient should acknowledge each packet by transmitting
    the total number of bytes received as an unsigned, 4 byte
    integer in network byte order. The sender should not continue
    to transmit until the recipient has acknowledged all data
    already transmitted. Additionally, the sender should not
    close the connection until the last byte has been
    acknowledged by the recipient.


http://www.irchelp.org/irchelp/rfc/dccspec.html
ah, daar is het probleem :) Dus als ik via socket_write de lengte terugstuur die ontvangen is hoort het te werken? * Peter gaat het in ieder geval proberen.

Acties:
  • 0 Henk 'm!

  • Radiant
  • Registratie: Juli 2003
  • Niet online

Radiant

Certified MS Bob Administrator

Yup, maar wel als integer.. Zie www.php.net/pack voor een mooie functie om te converteren + goeie byte order (network byte order is little endian).

Acties:
  • 0 Henk 'm!

  • Peter
  • Registratie: Januari 2005
  • Laatst online: 13-09 17:10
Gedaan, hij werkt nu redelijk, de bestanden worden totaal verstuurd mIRC denkt dat de bestanden in 1sec totaal verstuurd zijn, maar de server kan ze blijkbaar niet totaal downloaden (word maar 5 of 8 kb opgeslagen,van de 157 kb ). Dit is de code die ik nu heb, duidelijke fouten?

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$len = $times = 0;
$file = $data = "";

while( socket_recv($sock, $data, 512, 0) ){

    $file .= $data;
    $len += strlen( $data );
    
    $times++;
    if( $len < ( 512 * $times ) ){
        
        // keep-alive versturen
        socket_send( $sock, pack( "v", $len ), 4, 0 );
        
        }
    
    }

fwrite( $fn, $file );


Na de send lijkt hij compleet te stoppen met versturen?

[ Voor 16% gewijzigd door Peter op 12-06-2005 01:15 ]


Acties:
  • 0 Henk 'm!

  • Radiant
  • Registratie: Juli 2003
  • Niet online

Radiant

Certified MS Bob Administrator

v is een unsigned short, je moet de unsigned long hebben (V dus).
Het kan trouwens ook geen kwaad om gewoon na elke recv een ack te sturen, omdat je in veel IRC clients zelf de packet grootte in kan stellen en hoever hij mag doorsturen tot hij echt op een ack gaat wachten.

Acties:
  • 0 Henk 'm!

  • Peter
  • Registratie: Januari 2005
  • Laatst online: 13-09 17:10
zelfde probleem, hij blijft denken dat het totale bestand in 1 seconde verzonden is..

Acties:
  • 0 Henk 'm!

  • Radiant
  • Registratie: Juli 2003
  • Niet online

Radiant

Certified MS Bob Administrator

Mijn excuses, network byte order is big endian :o Net even opgezocht op wikipedia..
Wat test code geschreven en daarmee gaat het wel goed. N moet je dus hebben.

Acties:
  • 0 Henk 'm!

  • Peter
  • Registratie: Januari 2005
  • Laatst online: 13-09 17:10
Radiant schreef op zondag 12 juni 2005 @ 11:27:
Mijn excuses, network byte order is big endian :o Net even opgezocht op wikipedia..
Wat test code geschreven en daarmee gaat het wel goed. N moet je dus hebben.
Het werkt, perfect! Hardstikke bedankt :) Zou het topic nog even open mogen blijven? Vandaag ga ik verder met de module die bestanden kan versturen, dan kan ik dingen daarover eventueel indit topic zetten.

Acties:
  • 0 Henk 'm!

  • Ron!n
  • Registratie: Juli 2003
  • Laatst online: 18:42
klinkt als een heel interessante toepassing, zou het leuk vinden het is te testen :)

What's in the case?


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

.Peter schreef op zondag 12 juni 2005 @ 11:35:
Zou het topic nog even open mogen blijven?
Topics gaan hier niet op slot als ze opgelost zijn hoor. :) Andere mensen kunnen nog een betere oplossing willen bieden of ook mee willen discussiëren. ;)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Peter
  • Registratie: Januari 2005
  • Laatst online: 13-09 17:10
Ron!n schreef op zondag 12 juni 2005 @ 11:43:
klinkt als een heel interessante toepassing, zou het leuk vinden het is te testen :)
Sorry voor de ietswat late reactie, ik heb het nogal druk gehad :) Ik test de bot best vaak op IRC,

server: kaonashi.infi.org:6667
kanaal: #trivia
bot: Nishino

Als ik geen ''reclame'' mag maken voor de server, verwijder het gerust.

Ik ben nu net begonnen een de send-module :)
Pagina: 1