visual.tcl
4.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/morse/m3/bugnion/tcl-dp3.4b2/dpwish -f
#
# Copyright (C) 1996-1998 by the Board of Trustees
# of Leland Stanford Junior University.
#
# This file is part of the SimOS distribution.
# See LICENSE file for terms of the license.
#
#############################################################################
# visual
#
# Connects to a simos process, opens up the data stream. Ready to accept RPCs.
#
# The rpc interface takes a Tcl-SimoS script and sends the return value back
# the visual shell.
#
# Tcl-SimOS overloads the log command. logs that occur within the evaluation
# of an RPC script and during the interpreration of annotations that were
# installed by an RPC script will be written to a data stream handled by
# the visualization process.
#
# The data stream output can be in the form of Tcl scripts too. These
# will be evaluated within the context of the visual process.
# ProcessDataProc takes care of that
#
# ###########################################################################
proc visual {host port} {
global simosHost serverSocknum hostport localSockNum localHost
global listen_sd control_sd data_sd
global statsList
set simosHost $host
set serverSocknum $port
set hostport $host:$port
set localHost [exec hostname]
puts stdout "SimosHOST: $simosHost; SimosPORT $serverSocknum "; # taco
if {[catch ListenDataportProc errMsg]} {
error "Visual Error: $errMsg Couldn't setup data port."
}
if {[catch {ConnectSimosProc $simosHost $serverSocknum} errMsg]} {
error "Visual Error: $errMsg. \n Please make sure simos is running on host."
}
dp_filehandler $listen_sd r AcceptDataConnectProc
set msg "VISUALstream $localHost $localSockNum"
rpc $msg
}
################################################################################
# rpc
#
# Remote procedure call. The remote Tcl script will be interpreted within
# the SimOS interpreter. All Tcl-SimOS extensions may be used.
# The Tcl-SimOS log command has been overloeaded.
# Logs within RPCs and within annotations installed during an RPC
# will be send to the data stream and handled by ProcessDataProc
#
#
################################################################################
proc rpc { s } {
global control_sd
dp_send $control_sd $s
GetPacketProc $control_sd
}
proc ProcessDataProc { mode sd } {
global data_sd logfile
if {$sd != $data_sd} {
error "Visual Fatal Error Fatal error: Data socket descriptor screwup"
}
set x [GetPacketProc $sd]
# for debugging only: print out the script to be evaluated.
# ########################################################
puts "DataStream: $x"
# pretty generic. But do we really want to evaluate
# #### eval $x
}
proc ConnectSimosProc {simosHost serverSocknum} {
global localHost localSockNum listen_sd control_sd data_sd
# Pop up alert box that goes away after a while
puts stdout "Attempting to connect to $simosHost:$serverSocknum"
set returnVal [catch {dp_connect $simosHost $serverSocknum} connectResult]
if {$returnVal != 0} {
error "$connectResult" -1
}
puts stdout "Connection established"
set control_sd [lindex $connectResult 0]
dp_socketOption $control_sd autoClose no
dp_socketOption $control_sd noblock no
if {[lindex $connectResult 1] != $serverSocknum} {
set serverSocknum [lindex $connectResult 1]
}
}
proc AcceptDataConnectProc {mode sd} {
global listen_sd data_sd control_sd
# Let's pop up an alert box that goes away after a while
puts stdout "--> Accepting connection on data socket..."
if {$sd != $listen_sd} {
error "SimVisual Fatal Error: listen socket descriptor screwup"
}
dp_filehandler $listen_sd ;# Connection accepted, remove handler
set data_sd [lindex [split [dp_accept $listen_sd]] 0]
# dp_socketOption $data_sd autoClose no
dp_socketOption $data_sd noblock no
dp_filehandler $data_sd r ProcessDataProc
}
proc ListenDataportProc {} {
global listen_sd localSockNum maxSockNum
while {[catch {dp_connect -server $localSockNum -reuseAddr} \
localSockAndPort] && $localSockNum < 3001} {
incr localSockNum;
}
# 3999 is an arbitrary number. It allows for testing of 1000 different
# ports before giving up.
if { $localSockNum == $maxSockNum } {
error "Listen Data Port Error -- Can't get a local socket port"
}
set listen_sd [lindex [split $localSockAndPort] 0]
}
proc GetPacketProc {sd} {
set data ""
# first get the number of bytes of the packet
# ###########################################
set strlen "[dp_receive $sd 8]"
return [dp_receive $sd $strlen]
}
set localSockNum 2999 ; # Arbitrary value, goes upward if already used
set maxSockNum 3999 ; # Maximum value to try for localSockNum