Code: Select all
#### Get Rac Info ####
proc RacSkt {} {
global RacIP RacPort DetO DetAP DetPY DetPL MetaPY MetaPL
if {![info exists DetO]} {set DetO "offair.gif"; set DetAP "offair.gif"; set DetPY "offair.gif"; set DetPL "offair.gif"; set MetaPY "Not Available"; set MetaPL "Not Available"; return 0;};
if {[catch {set RacSock [socket -async $RacIP $RacPort]; fconfigure $RacSock -blocking 0;}]} {
set DetO "offair.gif";
set DetPY "offair.gif";
set DetPL "offair.gif";
set MetaPY "Not Available";
set MetaPL "Not Available";
return 0;
} else {
fileevent $RacSock writable [list RacNfo-A $RacSock];
};
}
proc RacNfo-A {RacSock} {
global DetO RacIP RacPort RacInfo
set DetO "onair.gif";
flush $RacSock;
puts $RacSock "GET /x/playing.cgi HTTP/1.0\r\nUser-Agent: Mozilla\r\nHOST $RacIP:$RacPort\r\n\r\n";
flush $RacSock;
set T 0; while {($T <= 100000)&&(![eof $RacSock])} {set RacInfo [gets $RacSock];};
flush $RacSock;
close $RacSock;
if {[catch {set RacSock [socket -async $RacIP $RacPort]; fconfigure $RacSock -blocking 0; }]} {
return 0;
} else {
fileevent $RacSock writable [list RacNfo-B $RacSock]
};
}
proc RacNfo-B {RacSock} {
global RacIP RacPort RacInfo PlayInfo DetO DetAP DetPY DetPL MetaPY MetaPL
flush $RacSock;
puts $RacSock "GET /x/playlist.cgi HTTP/1.0\r\nUser-Agent: Mozilla\r\nHOST $RacIP:$RacPort\r\n\r\n";
flush $RacSock;
set T 0; while {($T <= 100000)&&(![eof $RacSock])} {set PlayInfo [gets $RacSock];};
flush $RacSock;
close $RacSock;
if {($RacInfo == "")||($PlayInfo == "")} {return 0;};
#### Rac Chunk Parsers ####
parsers go here (theres a lot of them too)
}
Code: Select all
#### Get Cast Info ####
proc CastSkt {} {
global CastIP CastPort AdmLogin AdmPass DetI DetR DetS DetH DetL DetC DetDJ Mp3HC Mp3LC CamC Mp3HP Mp3LP CamP MetaT MetaS MetaDJ
if {![info exists DetH]} {set DetI "offair.gif"; set DetR "off
air.gif"; set DetS "offair.gif"; set DetH "offair.gif"; set DetL "off
air.gif"; set DetC "offair.gif"; set DetDJ "offair.gif"; set Mp3HC "N/A"; set Mp3LC "N/A"; set CamC "N/A"; set Mp3HP "N/A"; set Mp3LP "N/A"; set CamP "N/A"; set MetaT "Not Available"; set MetaS "Not Available";set MetaDJ "Not Available"; return 0;};
if {[catch {set CastSock [socket -async $CastIP $CastPort]; ##fconfigure $CastSock -blocking 0;}]} {
set DetI "offair.gif";
set DetR "offair.gif";
set DetS "offair.gif";
set DetH "offair.gif";
set DetL "offair.gif";
set DetC "offair.gif";
set DetDJ "offair.gif";
set Mp3HC "N/A";
set Mp3LC "N/A";
set CamC "N/A";
set Mp3HP "N/A";
set Mp3LP "N/A";
set CamP "N/A";
set MetaT "Not Available";
set MetaS "Not Available";
set MetaDJ "Not Available";
return 0;
} else {
fileevent $CastSock writable [list CastNfo $CastSock];
};
}
proc CastNfo {CastSock} {
global CastIP CastPort AdmLogin AdmPass CastInfo DetM DetI DetR DetS DetH DetL DetC DetDJ Mp3HC Mp3LC CamC Mp3HP Mp3LP CamP MetaT MetaS MetaDJ
set DetM "onair.gif";
flush $CastSock;
puts $CastSock "GET /Cast.xsl HTTP/1.0\r\nUser-Agent: Mozilla\r\nHOST $AdmLogin:$AdmPass@$CastIP:$CastPort\r\n\r\n";
flush $CastSock;
set T 0; while {($T <= 100000)&&(![eof $CastSock])} {set CastInfo "[read $CastSock]";};
flush $CastSock;
close $CastSock;
if {$CastInfo == ""} {return 0;};
#### Cast Chunk Parsers ####
again more parsers (anmd a lot of them)
}
Code: Select all
proc CastSkt {} {
global CastIP CastPort CastSock
if {([catch {set CastSock [socket $CastIP $CastPort];}])} {
putlog {Cast Socket NOT Detected...};
} else {
putlog {Cast Socket Detected!};
};
}
Code: Select all
proc RacSkt {} {
global RacIP RacPort RacSock
if {([catch {set RacSock [socket $RacIP $RacPort];}])} {
putlog {Rac Socket NOT Detected...};
} else {
putlog {Rac Socket Detected!};
};
}
Code: Select all
proc CastSkt {} {
global CastIP CastPort CastSock
if {([catch {set CastSock [socket -async $CastIP $CastPort]; fconfigure $CastSock -blocking off;}])} {
putlog {Cast Socket NOT Detected...};
} else {
putlog {Cast Socket Detected!};
};
}
proc RacSkt {} {
global RacIP RacPort RacSock
if {([catch {set RacSock [socket -async $RacIP $RacPort]; fconfigure $RacSock -blocking off;}])} {
putlog {Rac Socket NOT Detected...};
} else {
putlog {Rac Socket Detected!};
};
}
Code: Select all
proc RacSkt {} {
global RacIP RacPort RacSock
if {([catch {set RacSock [socket -async $RacIP $Ra
cPort]; fconfigure $RacSock -blocking off;}])} {
putlog {Rac Socket NOT Detected...};
} else {
putlog {Rac Socket Detected!};
fileevent $RacSock readable [list RacNfo $RacSock]
};
}
proc RacNfo {RacSock} {
flush $RacSock
close $RacSock
}
That is, use this instead when creating your socket:man n catch wrote:...
If the varName argument is given, then the variable it names is set to the result of the script evaluation. When the return code from the script is 1
(TCL_ERROR), the value stored in varName is an error message. When the return code from the script is 0 (TCL_OK), the value stored in resultVarName is
the value returned from script.
...
Code: Select all
...
if {[catch {socket -async $CastIP $CastPort} CastSock]} {
putlog "Cast Socket not created: $CastSock"
putlog "reason: $::errorInfo"
} else {
putlog "Cast Socket $CastSock created"
}
Are you trying to say that your services does not use http-transactions?dj-zath wrote:Now your examples didn't work either- because they work with the ASSUMPTION that the basic connection handlers follow protocol- which theese do -NOT-
yes.. THATS the problem!As such, we are currently relying on the underlying network layer to change the state of the channel to something like connection failed (and thus triggering tcl to close the channel identifier)
Code: Select all
#Straight after we've initated the connect and setup the first fileevent, add this:
after 30000 [list safeClose $socket]
...
#Also make sure our safeClose proc exists
proc safeClose {token} {
catch {close $token}
}
Code: Select all
after 30000 [catch {close $socket}]
Problem here is that you'd execute the catch {close $socket} command instantly, rather than delaying it 30 seconds.dj-zath wrote:hi again...
a couple things to update ya...
first.. couldn't I just use:
??Code: Select all
after 30000 [catch {close $socket}]
Please re-read my previous post, and it'll tell you exactly where to insert the correct code.. That is, _after_ you've initiated the (async) connection...dj-zath wrote:of course I can't! because the connection has to be made beforehand and thats were its getting locked up!
Could you post a showcase of this, including the code you were using?dj-zath wrote:fileevents aren't quite working either.. although "writable" reports ALL the time, "readable" doesn't report AT ALL! (or its intermittant at best).
Then you are doing something wrong, async by nature will return instantly, regardless of the state of the socket (or connection).dj-zath wrote:and even in async mode.. its STILL hanging on the initial connection...
I'm no expert in python, but as far as I can guess, python uses the very same underlying networking layer..dj-zath wrote:Also,
Someone wanted to try accessing the RAC connection for S&Gs, using python.. and he's having the same problems.. either no connection then connection to nowhere and/or connection but no data and a complete lockup/stall/crash of the script.. even in python, connection error-control is totally worthless!
Eggdrop doesn't ever see your NIC...dj-zath wrote:I've been wondering, myself if, in fact, its the onboard NIC on the server's motherboard thats causing the issues.. (the server that the eggie is residing) The RAC is on a windows box on the end of a WiMax (wireless) connection.. the NIC on the server is an Intel PRO/1000 MT DA (onboard) maaybe someone else out there might know of any issues with using this NIC with an eggie/TCL? tests to localhost all work properly and
"gets" returning noting: correct. Solution here is to use gets while retrieving the headers, and then switching over to read.dj-zath wrote:I have NO PROBLEMS with error-control or connection timeout/stalling issues with the icecast server running on the same box though there are issues if I try to run with "gets" instead of "read" which "gets" will render nothing.. I believe this is caused by icecast sending XSL output (and likely omitting any \r\n's) Which reminds me.. anyone out there know how I can set up a basic http auth to icecast?? I have tried NML's suggestion but that isn't accepting it.. icecast wants login:password@admin.server.com for login.. and TCL thinks theres a "sintax error"
Actually, your network issues are rather easily replicated with a WinXP system with firewall enabled. Just try to connect to an unused port, and the connection is silently dropped rather than refused. What I find very strange, is how you manage to freeze your application for several minutes. My 2.6 kernel will drop the connection attempt within 30 seconds without any kind of custom timeout code.dj-zath wrote:NML:
How would you like the opportunity to plug your code (your code, your way) into the RAC connection and try to reach the RAC? perhaps you'll better understand the problem(s) once you experience them yourself.. thing is, I'll need to know when you're doing it so I can "connect and disconnect" when the tests require it...
just let me know..
-DjZ-
![]()
Code: Select all
proc RunLoop1 {} {RacSkt; utimer 10 [list RunLoop1]; return 1;};
proc RunLoop2 {} {HeartBeat; utimer 10 [list RunLoop2]; return 1;};
proc RacSkt {} {
global RacIP RacPort
if {([catch {set RacSock [socket -async $RacIP $RacPort]; fconfigure $RacSock -blocking 0 -buffersize 10;}])||([catch {set PlaySock [socket -async $RacIP $RacPort]; fconfigure $PlaySock -blocking 0 -buffersize 10;}])} {
catch {close $RacSock};
catch {close $PlaySock};
return 0;
} else {
set CA [after 1800 [list close $RacSock];];
set CB [after 1800 [list close $PlaySock];];
fileevent $RacSock writable [list RacNfo $RacSock $CA];
fileevent $PlaySock writable [list PlayNfo $PlaySock $CB];
};
}
proc RacNfo {RacSock CA} {
global RacIP RacPort RacInfo
putlog {Rac Test}
if {([catch {after cancel $CA; flush $RacSock; puts $RacSock "GET /x/playing.cgi HTTP/1.0\r\nUser-Agent: Mozilla\r\nHOST $RacIP:$RacPort\r\n\r\n\r\n\r\n"; flush $RacSock; while {(![eof $RacSock])} {set RacInfo [gets $RacSock];}; catch {flush $RacSock}; catch {close $RacSock};}])} {
set RacInfo "";
return 0;
};
}
proc PlayNfo {PlaySock CB} {
global RacIP RacPort PlayInfo
putlog {Play Test}
if {([catch {after cancel $CB; flush $PlaySock; puts $PlaySock "GET /x/playlist.cgi HTTP/1.0\r\nUser-Agent: Mozilla\r\nHOST $RacIP:$RacPort\r\n\r\n\r\n\r\n"; flush $PlaySock; while {(![eof $PlaySock])} {set PlayInfo [gets $PlaySock];}; catch {flush $PlaySock}; catch {close $PlaySock};}])} {
set PlayInfo "";
return 0;
};
}
proc HeartBeat {} {
putlog {Still alive...};
}
Code: Select all
proc RacNfo {RacSock CA} {
global RacIP RacPort RacInfo
putlog {Rac Test}
if {
([catch {
after cancel $CA
flush $RacSock
puts $RacSock "GET /x/playing.cgi HTTP/1.0\r\nUser-Agent: Mozilla\r\nHOST $RacIP:$RacPort\r\n\r\n\r\n\r\n"
flush $RacSock
while {(![eof $RacSock])} {
set RacInfo [gets $RacSock]
}
catch {flush $RacSock}
catch {close $RacSock}
}])
} {
set RacInfo ""
return 0
}
}
A cleanup of your code, which should work (although I did not test it) follows... You'll end up with response headers aswell in RacInfo, so I guess you'll like to do some cleanup once the request is completed...A channel is considered to be writable if at least one byte of data can be written to the underlying file or device without blocking, or if an error condition is present on the underlying file or device.
Code: Select all
proc RacNfo {socket after} {
set ::RacInfo ""
after cancel $after
puts $socket "GET /x/playing.cgi HTTP/1.0\r\nUser-Agent: Mozilla\r\nHost: $::RacIP: $::RacPort\r\n\r\n"
if {[catch {flush $socket} status} {
putlog "Error in $socket: $status"
close $socket
return
}
fileevent $socket writable ""
fileevent $socket readable [list RacReadNfo $socket]
}
proc RacReadNfo {socket} {
if {[eof $socket]} {
putlog "Socket $socket is eof, closing..."
close $socket
return
}
append ::RacInfo [read $socket]
}