123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- # CIMS: Community IRC Messaging Service
- # CIMS formerly known as MNET (Message Network)
- # Multiple Network Interconnection MASTER Script
- # Copyright (C) 2004 Paul-Dieter Klumpp
- #
- # This program is free software; you can redistribute it and/or
- # modify it under the terms of the GNU General Public License
- # as published by the Free Software Foundation; either version 2
- # of the License, or (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- # vim: expandtab tabstop=2 shiftwidth=2 softtabstop=2 autoindent:
- namespace eval ::cims::interconnect {
- variable layout
- variable sshcommand {ssh}
- variable host {stomp@b4r.org}
- #set host "paul@localhost"
- variable mnet_interconnect_version "ic!0.1"
- }
- proc ::cims::interconnect::connect {} {
- variable sshcommand
- variable host
- variable pipe
- set command $sshcommand
- lappend command $host
- putlog "command is $command"
- if {[catch {
-
- if {![info exists pipe] || $pipe == ""} {
- set pipe [open "|$command" r+]
- fconfigure $pipe -translation binary -blocking 0 -buffering line
- } else {
- putlog "already connected here: $pipe"
- }
- } error]} {
- set pipe ""
- putlog "error $error"
- #conect again in a time
- } else {
- # read from console input
- ::cims::interconnect::readloop
- # check if connection is alive.. if not, reset it.
- ::cims::interconnect::pingloop
- }
- }
- proc ::cims::interconnect::connect_from_bind {nick mask hand chan text} {
- ::cims::interconnect::connect
- }
- proc ::cims::interconnect::disconnect {} {
- variable pipe
- ::cims::interconnect::send "PART"
- close $pipe
- set pipe ""
- }
- proc ::cims::interconnect::disconnect_from_bind {nick mask hand chan text} {
- ::cims::interconnect::disconnect
- }
- proc ::cims::interconnect::reconnect {} {
- ::cims::interconnect::disconnect
- ::cims::interconnect::connect
- }
- proc ::cims::interconnect::reconnect_from_bind {nick mask hand chan text} {
- ::cims::interconnect::reconnect
- }
- proc ::cims::interconnect::send {msg} {
- variable pipe
- if {$msg != "" && $pipe != ""} {
- putlog "writing $msg to pipe '$pipe'"
- if {[catch {
- puts $pipe "$msg"
- } error]} {
- close $pipe
- set pipe ""
- # well, it seems, our connection is broken, let's reconnect in 2 seconds.
- utimer 2 "::cims::interconnect::connect"
- }
- }
- }
- proc ::cims::interconnect::send_from_bind {nick mask hand chan text} {
- ::cims::interconnect::send "$text"
- }
- proc ::cims::interconnect::build_count_string {freqname source } {
- set bcid $::cims::interconnect::sources($freqname,$source)
- if {[info exists ::cims::interconnect::receive_count($bcid)]} {
- set count_list $::cims::interconnect::receive_count($bcid)
- set output_for_netbot "And to"
- foreach {item count} $count_list {
- set output_for_netbot "$output_for_netbot $count ${item},"
- }
- set output_for_netbot "[string range $output_for_netbot 0 [expr [string length $output_for_netbot] - 2]]"
- set output_for_netbot "${output_for_netbot}."
- return $output_for_netbot
- } else {
- return ""
- }
- }
- proc ::cims::timeout_reply_from_ic_for_netbot {netbot network freqname source} {
- set output_for_netbot [::cims::interconnect::build_count_string $freqname $source]
- if {"$output_for_netbot" != ""} {
- ::cims::put_bot $netbot "mnet_interconnect_answer $network $freqname $source [list $output_for_netbot]"
- }
- }
- proc ::cims::timeout_reply_from_local_for_ic {bcid network freqname source} {
- variable mnet_reached_users
- variable mnet_reached_userlist
- variable mnet_reached_chans
- # clean $name and $source
- set freqname [::putils::kill_spaces $freqname]
- #set source [::putils::kill_spaces $source]
- putlog "source: $source"
-
- # easify variables
- set userlist $mnet_reached_userlist($freqname,$source)
- set user_cnt [llength $userlist]
- set mnet_reached_users($freqname,$source) $user_cnt
- set chan_cnt $mnet_reached_chans($freqname,$source)
-
- # inzwischen drfte auch die antwort gekommen sein.. also jetzt mnet_reached_* auswerten nach timeout..
-
- # make stats channel-dependent
- #putlog "::cims:: * userlist is finally: $userlist "
- putlog "::cims:: * After ALL: Count_Users: $user_cnt Count_Channels: $mnet_reached_chans($freqname,$source)"
-
- # Give me some reply.
- ::cims::interconnect::send "BC_RE $bcid Users=$user_cnt,Channels=$chan_cnt"
- }
- # this proc is a new proc for cims.
- # the message came from interconnect and injects into the netbots and own channels
- proc ::cims::message_from_interconnect {network freqname source nick text} {
- variable mnet_reached_users
- variable mnet_reached_userlist
- variable mnet_reached_chans
- #putlog "freqname: $freqname"
- putlog "source: $source"
- #putlog "nick: $nick"
- #putlog "text: $text"
- # reset stats .. because he is just freshly sending
- set mnet_reached_users($freqname,$source) "0"
- set mnet_reached_userlist($freqname,$source) ""
- set mnet_reached_chans($freqname,$source) "0"
- ::cims::history_queue $network,$freqname $nick $source $text
-
- # send them first, we await a reply!
- # single sends TO ALL REMOTE BOTS with their remote CHANNELS...
- # let's see which mode for sending is used...
- ::cims::message_to_netbots $network $freqname $source $nick $text
-
- # SEND TO ALL OWN CHANNELS...
- # send to all own channels, except to the channel the message originating from:
- ::cims::message_to_own_channels $network $freqname $source $nick $text
-
- }
- proc ::cims::interconnect::add_up {bcid item count} {
- variable receive_count
- # schon drin?
- if {![info exists receive_count($bcid)]} {
- set receive_count($bcid) ""
- }
- set position [lsearch $receive_count($bcid) $item]
- if {$position > -1} {
- #putlog "item: $item is drin, weil posi $position"
- set the_old_count [lindex $receive_count($bcid) [expr $position + 1]]
- # the_old_count gets increased by $count
- incr the_old_count $count
- # we set it ..
- lset receive_count($bcid) [expr $position + 1] $the_old_count
- } else {
- #putlog "item: $item nicht drin, weil posi $position"
- lappend receive_count($bcid) "$item" "$count"
- }
-
- #putlog "hum: $receive_count($bcid)"
- }
- # called right before the output...
- proc ::cims::timeout_reply_from_local_for_netbots_plugin {freqname source} {
- upvar output output
- set add_output [::cims::interconnect::build_count_string $freqname $source]
- if {"$add_output" != ""} {
- set output "$output $add_output"
- }
- }
- # this is the stuff we read on the console.
- proc ::cims::interconnect::work {inputline} {
- variable broadcasts
- variable sources
- variable receive_count
- #putlog "work that out: $inputline"
- regexp -lineanchor {^.*\d: (.*)} $inputline matched sub
- putlog "subline: $sub"
- if {[regexp -all {^PONG} $sub] > 0} {
- #putlog "interconnect pong received"
- } elseif {[regexp -lineanchor -all {^(BC_ID) (.+) for: (.+),(.+),(.+)$} $sub whole command bcid network freqname source] > 0} {
- # this tells us, we sent a REQ_BC before.
- set broadcasts($bcid) [list "$network" "$freqname" "$source"]
- # keep that last message from $freqname,$source valid for 15 seconds
- set ::cims::interconnect::sources($freqname,$source) "$bcid"
- utimer 15 "unset ::cims::interconnect::sources($freqname,$source)"
- #putlog "bcid vars saved: $broadcasts($bcid) "
- # reset receive counters.
- set receive_user_count($bcid) 0
- set receive_item_count($bcid) 0
- } elseif {[regexp -lineanchor -all {^(BC_RE) (.+) (.+)=(\d+),(.+)=(\d+)$} $sub whole command bcid user_string user_count item_string item_count] > 0} {
- #BC_RE f4k3h4sh 5,3
- # central does some routing over central to make sure, the BC_RE message is only sent to me
- # ok cool .. i hope we sent a message with that $bcid before. And
- #.. we check on $bcid - find out the correct cims-vars (chan, freq, etc)
- # and add user_count, item_count to them.
-
- # now, let's validate that bcid .. we check if that bcid exists.. so the originating message is from me.
- if {[info exists broadcasts($bcid)] == 1} {
- set that $broadcasts($bcid)
- set network [join [lindex $that 0]]
- set freqname [join [lindex $that 1]]
- set source [join [lindex $that 2]]
- # count up
- ::cims::interconnect::add_up "$bcid" "$user_string" "$user_count"
- ::cims::interconnect::add_up "$bcid" "$item_string" "$item_count"
- # ready the variable, so it can be read from the plugin.
- set ::cims::interconnect::receive_count($bcid) "$::cims::interconnect::receive_count($bcid)"
- }
-
- } elseif {[regexp -lineanchor -all {^(BC) (.+) (.+),(.+),(.+),'(.+)','(.+)'$} $sub whole command bcid network freqname source nick text] > 0} {
- # THIS IS FRESH INPUT. ESCAPE IT.
- set freqname [split $freqname]
- set source [split $source]
- set nick [split $nick]
- set text [split $text]
- putlog "freqname: $freqname"
- putlog "source: $source"
- putlog "nick: $nick"
- putlog "text: $text"
- # parse here above.. or just use:
- #set network "QDEV"
- #set freqname "-dev-"
- #set source "http://qwnu"
- #set nick "testnickname"
- #set text "testmessage"
- # here, we read a message from central and put it to all local channels and netbots.
- ::cims::message_from_interconnect $network $freqname $source $nick $text
- # in the meantime, we even get all replies and counts (by ::cims::).
- # Now, we should get that count and send it to the central as a reply. Hitting the original sender.
- utimer 4 "::cims::timeout_reply_from_local_for_ic $bcid $network $freqname [list $source]"
-
- } elseif {[regexp -all {^WHO.*} $sub whole] > 0} {
- # ignore this one - it's fully handled by central.
- } elseif {[regexp -all -nocase {^C (.*): (.*)} $sub whole sub1 sub2] > 0} {
- # received, with command "C "
- if {"$sub2" != ""} {
- ::putils::put_local_msg "#aztest" "C $sub1: $sub2"
- }
- } else {
- # received, but it has no command
- #::putils::put_local_msg "#aztest" "not handled: $sub"
- }
- }
-
- proc ::cims::interconnect::read {} {
- variable pipe
- #putlog "into read"
- if {$pipe != ""} {
- #while { ![eof $pipe] } {
- gets $pipe inputline
- if {$inputline != ""} {
- ::cims::interconnect::work "$inputline"
- }
-
- #}
- }
- #putlog "ending of read"
- }
- proc ::cims::interconnect::readloop {} {
- variable pipe
- # check timers.. if old is running, don't start a new one
- set timerlist [utimers]
- set matched 0
- foreach {timerinfo} $timerlist {
- set timer_proc [join [lindex $timerinfo 1]]
- set timer_id [join [lindex $timerinfo 2]]
- if {[string match -nocase "::cims::interconnect::readloop" $timer_proc] == 1} {
- set matched 1
- }
- }
- if {$matched == 0 && $pipe != ""} {
- utimer 1 "::cims::interconnect::readloop"
- }
- # read a line
- ::cims::interconnect::read
- }
- proc ::cims::interconnect::ping {} {
- #putlog "into read"
- ::cims::interconnect::send "PING"
- }
- proc ::cims::interconnect::pingloop {} {
- variable pipe
- # check timers.. if old is running, don't start a new one
- set timerlist [utimers]
- set matched 0
- foreach {timerinfo} $timerlist {
- set timer_proc [join [lindex $timerinfo 1]]
- set timer_id [join [lindex $timerinfo 2]]
- if {[string match -nocase "::cims::interconnect::pingloop" $timer_proc] == 1} {
- set matched 1
- }
- }
- if {$matched == 0 && $pipe != ""} {
- utimer 160 "::cims::interconnect::pingloop"
- }
- # start a ping
- utimer 2 "::cims::interconnect::ping"
- }
- # this proc is a plugin proc for cims. it only gets executed if it exists.
- # the message came from our bot.
- proc ::cims::message_from_local_plugin {network freqname source nick text} {
- # send the message into central
- putlog "wo bin ich da? $source"
- ::cims::interconnect::send "REQ_BC $network,$freqname,$source,'$nick','$text'"
- # save BC_ID for this combination of parameters - is done in the above "::work"
- # receive answers from the other networks
- # prepare stats so that the local stats-counter takes it. the local stats are getting put out
- # at the end of ::cims::messaging_public_from_bind by ::cims::reply_timeout
- }
- # this proc is a plugin proc for cims. it only gets executed if it exists.
- # we received a message from a netbot
- proc ::cims::message_from_netbot_to_plugin {netbot network freqname source nick text} {
- # send the message into central
- ::cims::interconnect::send "REQ_BC $network,$freqname,$source,'$nick','$text'"
- # receive answers from the other networks
- # in the meantime, we get all the BC_RE replies and counts.
- # Now, we should get that count and send it to originating netbot.
- utimer 5 "::cims::timeout_reply_from_ic_for_netbot $netbot $network $freqname [list $source]"
- # send an own answer to the originating netbot
- }
- proc ::cims::interconnect::bindings {} {
- bind pub - !mnet_connect ::cims::interconnect::connect_from_bind
- bind pub - !mnet_disconnect ::cims::interconnect::disconnect_from_bind
- bind pub - !mnet_reconnect ::cims::interconnect::reconnect_from_bind
- bind pub - !mnet_input ::cims::interconnect::send_from_bind
- }
- proc ::cims::interconnect::main {} {
- variable mnet_interconnect_version
- variable pipe
- putlog "mnet! = mnet interconnection MASTER script loaded: $mnet_interconnect_version"
- ::cims::interconnect::bindings
- ::cims::interconnect::connect
- }
- namespace eval ::cims::interconnect {
- # timer weil $botnet-nick nicht sofort von eggdrop gesetzt wird
- utimer 3 "::cims::interconnect::main"
- }
|