Index of /tcl/ftparchive/sorted/net/demo
Name Last modified Size Description
Parent Directory 29-Jan-99 12:29 -
README 18-Jan-98 19:14 12k
demoCA/ 29-Jan-99 12:29 -
Demonstrations of how to use SSLtcl
Peter Antman
SSLtcl main program is a loadable module SSLtcl.so which can be loaded
by tclsh or wish at any time. It then gives the programmer access to
an extended version of tcl sockets. If you already know how to use the
socket command then read the manual page and get on with it.
If you feel unsure how to use sockets under tcl then have a look in
demo. There you find six example programs that utilize sockets with
SSL. They show different ways of configuring the socket under tcl.
The tcl socket command is among the most easiest ways to create
applications that can communicate over tcp/ip. Its most fundamental
aspect is that it either creates a client socket that directly tries
to connect to a server. Or it creates a server socket that listens on
the specified port and then creates additional sockets for each client
that connect so that is can service more than one client at a time.
To get tcl sockets to work in this nice way you have to have it in an
event loop and you have to configure the channel the socket is wrapped
in so that the program can take back command when it has started
serving a client.
The scripts in the demo directory contain different solutions to this
problem.
The scripts tstCli.tcl and tstSrv.tcl is two simple scripts that
utilize sockets and SSL in an easy way; but with the negative
sideffect that the server only will service one client at time.
Lets take a look at tstCli.tcl
9 set shouldbe [exec cat tstCli.tcl]
10 load ../SSLtcl.so SSLtcl
11
...
16 set s [socket -ssl -verify 1 -ciphers RC4-MD5 -cert demoCA/newcert.pem -key \
17 demoCA/newkey.pem -CAfile demoCA/cacert.pem localhost 443]
18
19 puts $s ''GET /''
20 puts ''Req complete''
21 flush $s
22 set got ''''
23 while { [gets $s l ] >= 0 } {
24 if { $got == '''' } {
25 set got $l
26 } else {
27 set got ''$got\n$l''
28 }
29 # puts ''RECV($l)''
30 }
31 close $s
32 puts ''Client done''
33 if { $got == $shouldbe } {
34 puts ''Client successful!!!''
35 } else {
36 puts ''Bummer!!! Client did not rec what it should have!''
37 exit -1;
38 }
39
As you see it loads in SSLtcl.so in line 10. SSLtcl.so is not as is
common under C based applications loaded from the best found location.
Therefore you have to specify the full path. For example
load /usr/local/lib/SSLtcl.so SSLtcl
tstCli.tcl is a string fall through application. On line 16 it opens a
socket and sets certain characteristics of it. Here we make it a
client socket which uses SSL. All possible options is used in this
example. The application will have its own certificate and will also
have a file which contain certificate from Certificate Authorities it
trusts. It also tells that it will only tolerate use of a special
cipher.
The socket command returns a channel identifier which we now can use
to read from and write to.
On line 19-21 the application writes to the socket and flushed the
channel so that it really sends something. Because we are using SSL
the communication with the server will take place over a cryptated
tunnel.
We then go in a loop and wait for something to read on the channel on
lone 23-29. When we get something we immediately closes the cannel, as
on line 31.
This could be the basis of a webbrowser fetching webpages. That is,
for a connectionless protocol.
The server tstSrv.tcl is not that useful for real life problems,
because it blocks while servicing clients. But is fairly easy to
understand.
9 set data [exec cat tstCli.tcl]
10
11 # This is the callback procedure that has to be part of the socket call
12 proc getit { s ip port args } {
13 global data
14 puts $args
15 puts ''Server socket ($s $ip $port)''
16 set req [gets $s];
17 puts ''RECV($req)''
18 if { $req == ''GET /'' } {
19 puts $s $data
20 } else {
21 puts ''UNKNOWN request''
22 puts $s ''UNKNOWN request''
23 }
24 close $s
25 }
26
27 # load the module, with full path to it
28 load ../SSLtcl.so SSLtcl
29 set s [socket -server getit -ssl -Verify 1 -cert \
30 demoCA/newcert.pem -key demoCA/newkey.pem \
31 -CAfile demoCA/cacert.pem 443]
32 puts $s
33 set tst 0
34 puts ''Server waiting connection on $s''
35
36 # Go into the eventloop
37 vwait tst
The main different between the client socket and a server socket is
that the application have to enter an event loop. A server program is
therefore not as straight a client program. Every server socket has to
have a command to call back when a request arrives.
At line 29 the channel is created. As we see we have to tell tcl that
wee want a server socket with the switch -server. This option have a
necessary argument, namely a callback command.
This is created on line 12-25. When a client connects this client will
be handed over to the callback command, in this case a procedure. The
procedure is rather straightforward. It read from the channel with
gets (line 16). Observe that this is not the same channel as that
returned by the socket command, but is a new channel given as a
argument to the procedure. It then writes back to the channel with
puts $channelid something.
At line 36 we went into an event loop. Nothing would have happen on
the socket channel before we did go into that loop because tcl would
not know how to handle the callback but would be busy doing other
things.
A connections is closed by closing the connection socket. The server
socket is closed first when you close the channel you got back from
the socket command.
To do something more useful one would like at least the server to be
able to respond to more than one client at a time. tstSrvReal is an
example of such a client. It is basically build on two callback. One
for the server socket to call, and one for every connections socket to
call. To get a callback from every socket when it need attention wee
have to configure it for that. This is done with the command filevent.
At line 36 you can see how it is used in this example.
9 # server writing back to client
10 proc getit_fork {s l} {
11 puts $s $l
12 flush $s
13 }
14
15 # the callback from filevent
16 proc getit_hand {s} {
17 puts filevent
18 set l [gets $s] ;# get the client packet
19 puts ''got $l''
20 if {[eof $s]} { ;# client gone or finished
21 close $s ;# release the servers client channel
22 } elseif {$l == ''Q''} {
23 close $s
24 exit
25 } elseif {$l == ''q''} {
26 close $s
27 return
28 } else {
29 getit_fork $s $l
30 }
31 }
32
33 # The connection callback, called from ssl
34 proc getit { s ip port args } {
35 puts ''in getit''
36 fileevent $s readable [list getit_hand $s]
37
38
39 fconfigure $s -buffering line -blocking 0
40 return
41
42 }
43
44 # load the module
45 load ../SSLtcl.so SSLtcl
46
47 # create socket, with ssl
48 set s [socket -server getit -ssl -Verify 1 -cert \
49 demoCA/newcert.pem -key demoCA/newkey.pem \
50 -CAfile /home/peter/ssl/demoCA/cacert.pem 443]
51 puts ''Server waiting connection on $s''
52
53 # Go into the eventloop
54 vwait events
The main part of the program is rather short. On line 45 to 54 we load
the module, creates the socket and goes into the event loop.
But in the callback procedure we give to the -server option we behave
differently. There we instead gives a new callback, configures the new
channel and returns so that the main program can continue on.
The filevent command is used to get tcl to call a procedure when there
is something happening on the cannel. In our case we want is to call
the procedure getit_hand when the channel is readable. And we send the
new channel as an argument.
We also configure the cannel. Especially useful is to configure it for
non blocking mode. If we do not do that the server will not be able to
service new client until the first connected has at least send
something, which means that a client could easily freeze the whole
server.
In the new callback we read in what's in the socket and examine its
connect. Useful is to check for End Of File, which is done on line 20
so that we know if the client has disappeared.
The stsCliReal.tcl is based on the same principles that tstSrvReal,
that is, we implement an event loop and a callback even in the client.
This is particularly good for connections that will be durable.
9 load ../SSLtcl.so SSLtcl
10
11 # I'm repeating this a few times to check for
12 # problems that may accumulate like file descriptor not being
13 # closed.
14 proc read_sock {sock} {
15 set l [gets $sock]
16 if {[eof $sock]} {
17 close $sock
18 set eventLoop ''done''
19 }
20 puts stdout ''ServerReply:$l''
21 }
22
23 # Read a line of text from stdin and send it to the echoserver socket,
24 # on eof stdin closedown the echoserver client socket connection
25 # this implements sending a message to the Server.
26 proc read_stdin {wsock} {
27 global eventLoop
28 set l [gets stdin]
29 puts ''l: $l''
30 if {[eof stdin]} {
31 close $wsock ;# close the socket client connection
32 set eventLoop ''done'' ;# terminate the vwait (eventloop)
33 } elseif {$l == ''Q''} {
34 puts $wsock $l
35 close $wsock
36 exit
37 } elseif {$l == ''q''} {
38 puts $wsock $l
39 close $wsock
40 exit
41 } else {
42 puts $wsock $l ;# send the data to the server
43 }
44 }
45
46 # Create the socket and ssl enables it
47 set s [socket -ssl -verify 1 -ciphers RC4-MD5 -cert demoCA/newcert.pem -key \
48 demoCA/newkey.pem -CAfile demoCA/cacert.pem localhost 443]
49
50 puts $s
51 fileevent $s readable [list read_sock $s]
52 fconfigure $s -buffering line
53 fileevent stdin readable [list read_stdin $s]
54 vwait eventLoop
55 puts ''Finished''
In this we create the socket and then a callback for that socket with
filevent on lines 47 and 51. We also creates a callback for
standardin. This means that we can type something on the screen at it
will be sent to the server. If something is on standardin we read it
and sends it to the server. If something is on the socket, we reads
it and prints it to the terminal. On line 54 we go into an eventloop
by waiting on an event on the variable eventLoop.
The two scripts tstSrvRealNoSSL.tcl and tstCliRealNoSSL.tcl is exactly
the same as the above scripts, except that they do not configure the
socket for SSL (but it uses the socket command provided by SSLtcl.)