File: timed.kvs

package info (click to toggle)
kvirc2 2.1.3-6
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 16,308 kB
  • ctags: 9,533
  • sloc: cpp: 86,257; sh: 10,532; makefile: 631; perl: 419; ansic: 315; sed: 16
file content (191 lines) | stat: -rw-r--r-- 5,695 bytes parent folder | download | duplicates (2)
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# A sample implementation of a time service daemon

# We define a subclass of socket (timedaemon)
# that listens on a specified port for incoming connections.
# Once a connection has been estabilished it creates
# a timeserversocket object that serves
# the client by responding to two commands:
# "time" that returns the current local time
# "date" that returns the current date
# Any other request is treated as an error and reported
# to the client with a warning message.
# The socket will serve a maximum of 5 valid client requests and
# then will disconnect and self-destroy, unless the client did it
# before.
# The socket will allow 3 consecutive invalid requests
# after that it will disconnect and self-destroy.

# To run this file drag it from the directory browser to
# the commandline input window, or use /PARSE filename.

# Define the server socket first
# (if it has not been already defined)
# This one starts already connected
# since the parent will call $accept on this socket.

if(!$classDefined(timeserversocket))
{
	class(timeserversocket,socket)
	{
		function(constructor)
		{
			# The base class is builtin, no need to call base constructor
			$this->%consecErrors = 0
			$this->%servedRequests = 0
			# Indicate success
			setreturn 1
		}

		event(OnDataReceived)
		{
			# Process the requests
			switch($2-)
			{
				case("time")
				{
					$this->$write("$time$cr$lf")
					$this->%consecErrors = 0
					$this->%servedRequests ++
				}
				case("date")
				{
					$this->$write("$date$cr$lf")
					$this->%consecErrors = 0
					$this->%servedRequests ++
				}
				default:
				{
					echo TIMESERVERSOCKET: invalid request from client $this->$host() on port $this->$port(): $2-
					$this->$write("Invalid request ($2-): valid requests are \"time\" and \"date\"$cr$lf")
					$this->%consecErrors ++
					if($this->%consecErrors == 3)
					{
						echo TIMESERVERSOCKET: too many consecutive errors for client $this->$host() on port $this->$port(): disconnecting
						$this->$dieNow("Too many errors (3). Goodbye!")
					}
				}
			}

			if($this->%servedRequests == 5)$this->$dieNow("Maximum of requests reached (5). Goodbye!")
		}

		event(OnDisconnect)
		{
			# The client has closed the connection; die silently
			destroy $this
		}

		function(dieNow)
		{
			$this->$write($1-)
			# Close is not strictly necessary since we will destroy the object
			# and the socket class will do it automatically...
			$this->$close()
			destroy $this
		}
	}
}

# Parent class: this one listens on the specified port
# for incoming connections.
# Once a connection arrives, it creates a server socket
# and calls $accept on it

if(!$classDefined(timedaemon))
{
	class(timedaemon,socket)
	{
		function(constructor)
		{
			# The base class is builtin, no need to call base constructor.
			# Auto-listen on a specified port.
			if(!$isNumber("$1"))
			{
				# No port number specified. Just refuse to work and die
				echo TIMEDAEMON: missing port number in constructor
				# Failed
				setreturn 0
				halt
			}

			if(!$this->$listen(default,$1))
			{
				# Listen failed
				echo TIMEDAEMON: failed to listen on port $1
				echo TIMEDAEMON: error: $this->$lastError()
				# Failed
				setreturn 0
			} else {
				# Success
				echo TIMEDAEMON: listening on port $1
				setreturn 1
			}
		}

		event(OnIncomingConnection)
		{
			%o = $new(timeserversocket,$this,yahoo)
			if(!%o->$accept($this))
			{
				echo TIMEDAEMON: accept failed: %o->$lastError()
				destroy %o
			} else {
				echo TIMEDAEMON: serving %o->$host() on port %o->$port()
			}
		}
	}
}


# Now let's create a daemon instance

%TimeDaemon = $new(timedaemon,$root,timedaemon,5555)

echo TIMED: service started
echo To test this service you can telnet to localhost on port 5555
echo To stop the service use /destroy \%TimeDaemon
echo Have fun!

# Yup, the service should be up and running now
# If you want to test it just type the following in the commandline
# %Test = $new(socket,$root,testobj)
# %Test->$connect(127.0.0.1,5555)
# %Test->$write("time$cr$lf")
# %Test->$write("date$cr$lf")
# %Test->$close()
# and so on :)

# To kill the service call "destroy %TimeDaemon"

#
# Here are a few common commands and output from a test session
#
# /PARSE /usr/share/doc/kvirc/script-examples/timed.kvs
# ...
# [14:10:11] TIMEDAEMON: listening on port 5555
# [14:10:29] TIMEDAEMON: serving 127.0.0.1 on port 1035
# /%T = $new(socket,$root,testsock)
# /%T->$connect(127.0.0.1,5555)
# [14:10:29] SOCKET @3: connected to 127.0.0.1 on port 5555
# /%T->$write("time$cr$lf")
# [14:10:37] SOCKET @3: received data: 14:10:37
# /%T->$write("date$cr$lf")
# [14:10:41] SOCKET @3: received data: Thu Feb 17 2000
# /%T->$write("foo$cr$lf")
# [14:10:44] TIMESERVERSOCKET: invalid request from client 127.0.0.1 on port 1035: foo
# [14:10:44] SOCKET @3: received data: invalid request (foo): valid requests are "time" and "date"
# /%T->$write("gugu$cr$lf")
# [14:10:57] TIMESERVERSOCKET: invalid request from client 127.0.0.1 on port 1035: gugu
# [14:10:57] SOCKET @3: received data: invalid request (gugu): valid requests are "time" and "date"
# /%T->$write("pippo$cr$lf")
# [14:11:00] TIMESERVERSOCKET: invalid request from client 127.0.0.1 on port 1035: pippo
# [14:11:00] TIMESERVERSOCKET: too many consecutive errors for client 127.0.0.1 on port 1035: disconnecting
# [14:11:00] SOCKET @3: received data: invalid request (pippo): valid requests are "time" and "date"
# [14:11:00] SOCKET @3: disconnected from 127.0.0.1: remote end closed connection
# /destroy %T
#

# There can be many alternative implementations of this service
# You can embed it in aliases or system events.
# Add/remove functionality.
# Well, have fun!