1 # tcp.tcl --
2 #
3 # FIXME: This file needs a description here.
4 #
5 # Copyright (c) 1997-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/tcp.tcl,v 1.13 2002/02/03 04:28:06 lim Exp $
32
33
34 #
35 # A base class for TCP client and server connections.
36 #
37 Class TCP
38
39 #
40 # A base class for TCP server connections.
41 #
42 Class TCP/Server -superclass TCP
43
44 #
45 # A base class for TCP client connections.
46 #
47 Class TCP/Client -superclass TCP
48
49 TCP public destroy {} {
50 $self close
51 $self next
52 }
53
54 #
55 # virtual method called when far end closes
56 #
57 TCP public shutdown {} {
58 }
59
60
61 TCP public set_binary { {flag 1} } {
62 $self instvar chan_
63 if { $flag } {
64 fconfigure $chan_ -translation {binary binary}
65 } else {
66 fconfigure $chan_ -translation {auto auto}
67 }
68 }
69
70
71 TCP public open { chan {blocking 0} } {
72 $self instvar chan_
73 #FIXME should do async open
74 set chan_ $chan
75 fileevent $chan_ readable "$self readable"
76 if { $blocking } {
77 fconfigure $chan_ -blocking true
78 } else {
79 fconfigure $chan_ -blocking false
80 }
81 }
82
83
84 TCP public is_open { } {
85 $self instvar chan_
86 if { [info exists chan_] && ![eof $chan_] } {
87 return 1
88 }
89 return 0
90 }
91
92
93 TCP public close {} {
94 $self instvar chan_
95 if [info exists chan_] {
96 close $chan_
97 unset chan_
98 }
99 }
100
101
102 TCP public channel {} {
103 $self instvar chan_
104 if [info exists chan_] { return $chan_ } else { return "" }
105 }
106
107
108 TCP private readable {} {
109 $self instvar chan_
110 set cnt [gets $chan_ s]
111 if { $cnt < 0 } {
112 if [eof $chan_] {
113 $self close
114 $self shutdown
115 #FIXME how to delete ourself?
116 }
117 return
118 }
119 # count of zero might be single newline (FIXME which is stripped...)
120 if { $cnt >= 0 } {
121 $self recv $s
122 }
123 }
124
125
126 TCP public send s {
127 $self instvar chan_
128 puts -nonewline $chan_ $s
129 #FIXME
130 flush $chan_
131 }
132
133
134 #
135 # FIXME hack since otcl methods can't deal with binary strings
136 #
137 TCP public send_data {} {
138 $self instvar chan_ data_
139 puts -nonewline $chan_ $data_
140 #FIXME
141 flush $chan_
142 }
143
144
145 TCP public sendline s {
146 $self instvar chan_
147 puts $chan_ $s
148 #FIXME
149 flush $chan_
150 }
151
152
153 # The application must redefine this method in a sub-class
154 # It is invoked every time a line is received from the socket
155 TCP public recv s {
156 }
157
158
159 TCP/Client public init args {
160 }
161
162
163 #
164 # Open a TCP connection to the Internet host <i>host</i>
165 # on the TCP port <i>port</i>
166 #
167 TCP/Client public open { host port {blocking 0} } {
168 $self instvar chan_
169 #FIXME should do async open
170 set chan_ [socket $host $port]
171 fileevent $chan_ readable "$self readable"
172 if { $blocking } {
173 fconfigure $chan_ -blocking true
174 } else {
175 fconfigure $chan_ -blocking false
176 }
177 }
178
179
180 #
181 # Open a TCP listen socket on port <i>port</i>.
182 # When a client connects to this port, the virtual method
183 # TCP/Server::create_channel is called to create
184 # a TCP object.
185 # <p>
186 # The <i>create_channel</i> argument can either be the
187 # name of a class (typically subclassed from TCP) --
188 # the TCP/Server object will create an object of that
189 # class whenever it receives a TCP connection. From
190 # that point on, this object can communicate with
191 # the remote side using the normal TCP API.
192 # Alternatively, the <i>create_channel</i> argument
193 # may be a command to invoke when the TCP/Server
194 # object receives a connection. The command must take
195 # a Tcl channel id as an argument.
196 # <p>
197 # Finally, you may simply not specify the <i>create_channel</i>
198 # argument, and redefine the <i>create_channel</i> method in a
199 # subclass of TCP/Server
200 #
201 TCP/Server public open { port {create_channel {}} } {
202 $self instvar chan_ client_class_ create_channel_proc_
203 #FIXME should do async open
204 set chan_ [socket -server "$self accept" $port]
205 if { $create_channel != {} } {
206 # first check if this is a class name
207 if { [Class info instances $create_channel]!="" } {
208 set client_class_ $create_channel
209 } else {
210 set create_channel_proc_ $create_channel
211 }
212 }
213 }
214
215
216 TCP/Server public close { } {
217 $self instvar client_class_ create_channel_proc_
218 if [info exists client_class_] {
219 unset client_class_
220 }
221
222 if [info exists create_channel_proc_] {
223 unset create_channel_proc_
224 }
225
226 $self next
227 }
228
229
230 TCP/Server private accept { chan host port } {
231 set o [$self create_channel $chan]
232 }
233
234
235 #
236 # The default create_channel method creates a channel
237 # object whenever the server receives a TCP connection
238 # Look at <i>TCP/Server::open</i> for details.
239 #
240 TCP/Server private create_channel { chan } {
241 $self instvar client_class_ create_channel_proc_
242 if [info exists create_channel_proc_] {
243 eval $create_channel_proc_ $chan
244 } elseif [info exists client_class_] {
245 set o [new $client_class_]
246 $o open $chan
247 } else {
248 error "must redefine TCP/Server::create_channel in a subclass\
249 \nor specify a channel creation mechanism in\
250 TCP/Server::open"
251 }
252 }
253
254
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.