~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Open Mash Cross Reference
mash/tcl/net/udpserver.tcl

Component: ~ [ mash ] ~ [ apps ] ~ [ gsm ] ~ [ lib ] ~ [ otcl ] ~ [ srm ] ~ [ tcl8.3 ] ~ [ tclcl ] ~ [ tk8.3 ] ~ [ tutorials ] ~

  1 # udpserver.tcl --
  2 #
  3 #       FIXME: This file needs a description here.
  4 #
  5 # Copyright (c) 1996-2002 The Regents of the University of California.
  6 # All rights reserved.
  7 #
  8 # Redistribution and use in source and binary forms, with or without
  9 # modification, are permitted provided that the following conditions are met:
 10 #
 11 # A. Redistributions of source code must retain the above copyright notice,
 12 #    this list of conditions and the following disclaimer.
 13 # B. Redistributions in binary form must reproduce the above copyright notice,
 14 #    this list of conditions and the following disclaimer in the documentation
 15 #    and/or other materials provided with the distribution.
 16 # C. Neither the names of the copyright holders nor the names of its
 17 #    contributors may be used to endorse or promote products derived from this
 18 #    software without specific prior written permission.
 19 #
 20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
 21 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 22 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 23 # ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
 24 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 25 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 26 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 27 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 28 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 30 #
 31 # @(#) $Header: /usr/mash/src/repository/mash/mash-1/tcl/net/udpserver.tcl,v 1.10 2002/02/03 04:28:06 lim Exp $
 32 
 33 
 34 import UDPChannel
 35 
 36 # UDPChannel that maintains list of unicast
 37 # address/port pairs and optionally also a single mcast address/port;
 38 # all are sent data when 'send' is called.
 39 # It automatically times out addrs that haven't been refreshed in
 40 # 'timeout_' seconds (if timeout_ == 0 they persist forever);
 41 # the list can also be manually manipulated via
 42 # 'addAddr' and 'rmAddr' and 'timeoutAddrs'
 43 #
 44 Class UDPServer -superclass UDPChannel
 45 
 46 # spec indicates the port number to listen on; additionally,
 47 # if spec is a multicast addr, it is used in addition to unicast addrs
 48 # as a location to send 'announce' messages
 49 #
 50 UDPServer public init { {spec ""} {mtu 1024} } {
 51     $self instvar replyToList_ mcastAddr_ port_ child_ timeout_
 52 
 53     set timeout_ 60 ; # default timeout is 60 secs
 54     set replyToList_ ""
 55     set replyTimeList_ ""
 56 
 57     if [regexp {^[0-9]*$} $spec] {
 58         set port_ $spec
 59         set addr ""
 60     } else {
 61         set port_ [lindex [split $spec "/"] 1]
 62         set addr [lindex [split $spec "/"] 0]
 63         # if spec includes a name, turn it into IP addr
 64         set firstchar [string index $spec 0]
 65         if [string match \[a-zA-Z\] $firstchar] {
 66             set n [lindex [split $spec "/"] 0]
 67             set s [gethostbyname $n]
 68             if { $s == "" } {
 69                 puts "cannot find address for '$n'"
 70                 exit
 71             }
 72             set addr $s
 73         }
 74 
 75     }
 76     # addressblocks only allow even ports -- emulate this
 77     if {$port_ % 2 != 0} {
 78         puts "WARNING: you specified an odd port: decrementing 1"
 79         incr port_ -1
 80     }
 81 
 82     if {$addr != ""} {
 83         if [in_multicast $addr] {
 84             $self next $spec $mtu
 85             set mcastAddr_ $addr/$port_
 86             set child_ [new UDPServerChild $self $port_]
 87         } else {
 88             set mcastAddr_ -1
 89             set child_ [new UDPServerChild $self $addr/$port_]
 90         }
 91     } else {
 92         set mcastAddr_ -1
 93         set child_ [new UDPServerChild $self $port_]
 94     }
 95 
 96 }
 97 
 98 # add addr and/or refresh last update time
 99 # for addrspec in replyToList_
100 UDPServer public addAddr {addrspec} {
101     $self instvar replyToList_ replyTimeList_
102 
103     set l [lsearch $replyToList_ $addrspec]
104     if {$l == -1} {
105         lappend replyToList_ $addrspec
106         lappend replyTimeList_ [clock seconds]
107     } else {
108         set replyTimeList_ [lreplace $replyTimeList_ $l $l [clock seconds]]
109     }
110 }
111 
112 # remove addr from replyTo list
113 UDPServer public rmAddr {addrspec} {
114     $self instvar replyToList_ replyTimeList_
115 
116     set loc [lsearch $replyToList_ $addrspec]
117     if {$loc != -1} {
118         set replyToList_ [lreplace $replyToList_ $loc $loc]
119         set replyTimeList_ [lreplace $replyTimeList_ $loc $loc]
120     } else {
121         puts "UDPServer: Tried to remove addr not in reply list: `$addrspec'"
122     }
123 }
124 
125 # remove any addr not updated in last <em>timeout</em> seconds
126 #
127 UDPServer public timeoutAddrs {timeout} {
128     $self instvar replyToList_ replyTimeList_
129 
130     if {$replyToList_ == ""} {return}
131     set t [clock seconds]
132     if {[llength $replyToList_] != [llength $replyTimeList_]} {
133         puts "Error: reply lists lengths are different! \
134                 [llength $replyToList_] != [llength $replyTimeList_]"
135     }
136     set cnt 0
137     foreach i $replyTimeList_ {
138         if {[expr $t - $i] > $timeout} {
139             $self rmAddr [lindex $replyToList_ $cnt]
140         }
141         incr cnt
142     }
143 }
144 
145 # send <em>data</em> to everyone
146 #
147 UDPServer public announce {data} {
148     $self instvar replyToList_ mcastAddr_ port_ timeout_
149 
150     if {$timeout_ > 0} {
151         $self timeoutAddrs $timeout_
152     }
153 
154     foreach i $replyToList_ {
155         #puts "$i: $data"
156         set sender [new UDPChannel $i]
157         $sender send "$data"
158         delete $sender
159         after 50
160     }
161     if {$mcastAddr_ != -1} {
162         $self send "$data"
163     }
164 
165     # FIXME backward compatability: for clients that listen on the port
166     # number they send to (i.e., well-known rather than ephemeral)
167     regsub -all "/" "$replyToList_" " " tmp
168     array set addrsOnly $tmp
169     foreach i [array names addrsOnly] {
170         set sender [new UDPChannel $i/$port_]
171         $sender send "$data"
172         delete $sender
173     }
174 }
175 
176 # set new timeout value
177 UDPServer public timeout {t} {
178     $self instvar timeout_
179     set timeout_ $t
180 }
181 
182 # Receive Stub: should be extended by subclasses
183 UDPServer private recv {addr port data len} {
184     puts "Msg from $addr/$port \[$len\]: $data"
185 }
186 
187 
188 # -----------
189 
190 # UDPServerChild is a UDPServer helper class: it simply monitors a
191 # unicast address and passes along received packets to the parent
192 # after adding the addresses to the replyTo list
193 Class UDPServerChild -superclass UDPChannel
194 
195 #
196 UDPServerChild instproc init {parent spec {mtu 1024}} {
197     #puts "listening to unicast $spec"
198     $self next $spec $mtu
199     $self instvar parent_
200     set parent_ $parent
201 }
202 
203 #
204 UDPServerChild instproc recv {addr port data size} {
205     #puts "UDPServerChild::recv"
206     $self instvar parent_
207     $parent_ addAddr $addr/$port
208     $parent_ recv $addr $port "$data" $size
209 }
210 
211 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.