This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

Sockets and rehashing

Help for those learning Tcl or writing their own scripts.
Post Reply
t
tintin
Voice
Posts: 5
Joined: Thu Feb 07, 2013 3:25 am

Sockets and rehashing

Post by tintin »

So once again I'm having some issues, going somewhat out of my depth with coding, but hey thats how we learn.

I wrote/borrowed parts to this script that announces data to channels of posts reports so on and so forth from the forums, there is no real problem with that part. Where the issue lies is when the bot is rehashed or restarted it can't reopen the port because its already open.

So the part that is out of my depth is getting the script not to kill the bot just because it can't open the port again and either closing or just start listening again whichever better.

Here is all the relevant code to the script.

Code: Select all

# port for your script you want to listen on (you need to set same port in php script)
set botlisten(port) "16384"
set botlisten(ip) "127.0.0.1"
#Bot listen password. This currently isnt used its only listening to the localhost so no external siglnals can get to it. use only if hosting on a different server
set botlisten(password) ""
# channel you want to send output to
set botlisten(devchan) "#Admins"

set serverSocket [socket -server main -myaddr $botlisten(ip) $botlisten(port)]



proc main { sock host port } {
	fconfigure $sock -buffering line
	fileevent $sock readable [action $sock $host $port]
}

proc action { chan host port } {
	global botlisten
	
	if {![eof $chan]} { 
               set soc_data [gets $chan] 
				putlog $soc_data
                if {$soc_data != ""} { 
                        #This Relays what ever the bot is sending to the selected channel, this could also be a user
						putquick "PRIVMSG $botlisten(devchan) :$soc_data" 
						putquick "$soc_data"
                } 
        } { 
                close $chan 
        } 
} 
I'm guessing I have to use the catch command but I can't quite get my head around it. However I am open to any different ways you guys might suggest. :)

Thanks for the help, its always appreciated
d
dirty
Halfop
Posts: 40
Joined: Fri Feb 08, 2013 2:33 pm
Location: Romania
Contact:

Post by dirty »

Try this:

Code: Select all

if {![info exists serverSocket]} {
        set serverSocket [socket -server main -myaddr $botlisten(ip) $botlisten(port)]
}
Instead of this:

Code: Select all

set serverSocket [socket -server main -myaddr $botlisten(ip) $botlisten(port)]
come to the dark side.. I have cookies!
WwW.BotZone.TK
User avatar
caesar
Mint Rubber
Posts: 3778
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

Or how about checking user's socket api - nonblocking tcp made easy?

But, if you are fetching some info off a web page, why don't you just use http package instead?
Once the game is over, the king and the pawn go back in the same box.
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

It does seem a little scary sending unauthenticated data directly to the irc server:

Code: Select all

putquick "$soc_data"
Although you are listening to the loopback interface, anyone using that machine would still be able to connect to that port. If this is a private server (not VPS), where you are in full control of how accesses the server, I guess it would'nt be that horrible - yet still worth mentioning...

As for the opening of the listen-socket, it should remain open for the duration of the tcl interpreter, so there should be no need to re-open it on a .rehash (hence the error you get). I don't quite recall if it'll persist through .restart, though I do know that the ::serveSocket variable will not.

If dirty's suggestion works for you, go with it. Looks proper enough..

As for the catch command, it's use is not so difficult;
First argument is a command string (be aware of "double evaluations" though).
The second (optional) argument is the name of a variable holding either the error code (if TCL_ERROR), or the result of the command (if TCL_OK);

Code: Select all

catch {socket -server main -myaddr $botlisten(ip) $botlisten(port)} serverSocket
If you'd like to test whether the command was successful, add an if-block;

Code: Select all

if {[catch {socket -server main -myaddr $botlisten(ip) $botlisten(port)} serverSocket]} {
  putlog "Unable to open listening port: $serverSocket"
}
As for ceasar's suggestion, the http-package will not work, as you obviously are not fetching web pages...
NML_375
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Actually...
In this rather trivial example, you might just be better off using eggdrop's own socket handling: listen, and control

Code: Select all

listen $::botlisten(port) acceptConnection

proc acceptConnection {idx} {
  control $idx readLine
}

proc readLine {idx text} {
  if {$text != ""} {
    putquick "PRIVMSG $::botlisten(devchan) :$text"
  }
}
The downside would be that you can't directly control which IP "listen" will use (you can control it indirectly by using the ::my_ip and/or ::my_hostname variables, though they affect all sockets opened by eggdrop).
NML_375
User avatar
speechles
Revered One
Posts: 1398
Joined: Sat Aug 26, 2006 10:19 pm
Location: emerald triangle, california (coastal redwoods)

Post by speechles »

Code: Select all

# port for your script you want to listen on (you need to set same port in php script)
set botlisten(port) "16384"
set botlisten(ip) "127.0.0.1"
#Bot listen password. This currently isnt used its only listening to the localhost so no external siglnals can get to it. use only if hosting on a different server
set botlisten(password) ""
# channel you want to send output to
set botlisten(devchan) "#Admins"

if {![info exists serverSocket]} {
   set serverSocket [socket -server main -myaddr $botlisten(ip) $botlisten(port)]
}

proc main { sock host port } {
   fconfigure $sock -buffering line
   fileevent $sock readable [action $sock $host $port]
} 

proc action { chan host port } {
   global botlisten
   set soc_data [gets $chan]
   if {![eof $chan]} {
      outputAction $soc_data $botlisten(devchan)
      set soc_data [gets $chan]
   } else {
      outputAction $soc_data $botlisten(devchan)
      close $chan
   }
}

proc outputAction { soc_data chan } {
   putlog $soc_data
   if {[string length $soc_data]} {
      #This Relays what ever the bot is sending to the selected channel, this could also be a user
       putquick "PRIVMSG $chan :$soc_data"
   }
   
}
I always thought you had to [gets] before you could detect eof. So here's my take on what it should look like.. haw ;)
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Too many "gets" in there, but otherwise fine.

You do need to read the last line (with gets or read) in order for "eof" to return true, but the fileevent will also fire if there is an eof-condition on the channel. Thus, both ways will work well.
NML_375
User avatar
caesar
Mint Rubber
Posts: 3778
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

I've read in a hurry something about PHP and assumed it's fetching something from a web server. But my first suggestion, meaning user's code, should be useful.
Once the game is over, the king and the pawn go back in the same box.
Post Reply