]>
code.delx.au - pymsnt/blob - src/main.py
1 # Copyright 2004-2005 James Bunton <james@delx.cjb.net>
2 # Licensed for distribution under the GPL version 2, check COPYING for details
11 sys
. setdefaultencoding ( "utf-8" )
13 # Must load config before everything else
16 xmlconfig
. reloadConfig ()
18 from twisted
. internet
import reactor
, task
19 from twisted
. internet
. defer
import Deferred
20 from tlib
. xmlw
import Element
, jid
, component
21 from debug
import LogEvent
, INFO
, WARN
, ERROR
36 #gc.set_debug(gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_INSTANCES | gc.DEBUG_OBJECTS)
39 class PyTransport ( component
. Service
):
43 # Do any auto-update stuff
46 # Discovery, as well as some builtin features
47 self
. discovery
= disco
. ServerDiscovery ( self
)
48 self
. discovery
. addIdentity ( "gateway" , legacy
. id , legacy
. name
, config
. jid
)
49 self
. discovery
. addIdentity ( "conference" , "text" , legacy
. name
+ " Chatrooms" , config
. jid
)
50 self
. discovery
. addFeature ( disco
. XCONFERENCE
, None , config
. jid
) # So that clients know you can create groupchat rooms on the server
51 self
. discovery
. addFeature ( "jabber:iq:conference" , None , config
. jid
) # We don't actually support this, but Psi has a bug where it looks for this instead of the above
53 self
. xdb
= xdb
. XDB ( config
. jid
, legacy
. mangle
)
54 self
. avatarCache
= avatar
. AvatarCache ()
55 self
. registermanager
= register
. RegisterManager ( self
)
56 self
. gatewayTranslator
= misciq
. GatewayTranslator ( self
)
57 self
. versionTeller
= misciq
. VersionTeller ( self
)
58 self
. pingService
= misciq
. PingService ( self
)
59 self
. adHocCommands
= misciq
. AdHocCommands ( self
)
60 self
. vCardFactory
= misciq
. VCardFactory ( self
)
61 self
. iqAvatarFactor
= misciq
. IqAvatarFactory ( self
)
62 self
. connectUsers
= misciq
. ConnectUsers ( self
)
63 if config
. ftJabberPort
:
64 self
. ftSOCKS5Receive
= ft
. Proxy65 ( int ( config
. ftJabberPort
))
65 self
. ftSOCKS5Send
= misciq
. Socks5FileTransfer ( self
)
67 self
. ftOOBReceive
= ft
. FileTransferOOBReceive ( int ( config
. ftOOBPort
))
68 self
. ftOOBSend
= misciq
. FileTransferOOBSend ( self
)
69 self
. statistics
= misciq
. Statistics ( self
)
70 self
. startTime
= int ( time
. time ())
75 # Groupchat ID handling
82 self
. loopCall
= task
. LoopingCall ( self
. loopCall
)
83 self
. loopCall
. start ( 60.0 )
87 for session
in self
. sessions
. copy ():
88 self
. sessions
[ session
]. removeMe ()
90 def makeMessageID ( self
):
92 return str ( self
. messageID
)
95 newID
= "r" + str ( self
. lastID
)
97 if self
. reservedIDs
. count ( newID
) > 0 :
98 # Ack, it's already used.. Try again
103 def reserveID ( self
, ID
):
104 self
. reservedIDs
. append ( ID
)
107 numsessions
= len ( self
. sessions
)
109 #if config.debugOn and numsessions > 0:
111 # for key in self.sessions:
112 # print "\t" + self.sessions[key].jabberID
114 self
. statistics
. stats
[ "Uptime" ] = int ( time
. time ()) - self
. startTime
115 self
. statistics
. stats
[ "OnlineUsers" ] = numsessions
116 legacy
. updateStats ( self
. statistics
)
118 oldDict
= self
. sessions
. copy ()
121 session
= oldDict
[ key
]
122 if not session
. alive
:
123 LogEvent ( WARN
, "" , "Ghost session found." )
124 # Don't add it to the new dictionary. Effectively removing it
126 self
. sessions
[ key
] = session
128 def componentConnected ( self
, xmlstream
):
130 self
. xmlstream
= xmlstream
131 self
. xmlstream
. addObserver ( "/iq" , self
. discovery
. onIq
)
132 self
. xmlstream
. addObserver ( "/presence" , self
. onPresence
)
133 self
. xmlstream
. addObserver ( "/message" , self
. onMessage
)
134 self
. xmlstream
. addObserver ( "/route" , self
. onRouteMessage
)
136 pres
= Element (( None , "presence" ))
137 pres
. attributes
[ "to" ] = "presence@-internal"
138 pres
. attributes
[ "from" ] = config
. compjid
139 x
= pres
. addElement ( "x" )
140 x
. attributes
[ "xmlns" ] = "http://www.jabber.com/schemas/component-presence.xsd"
141 x
. attributes
[ "xmlns:config" ] = "http://www.jabber.com/config"
142 x
. attributes
[ "config:version" ] = "1"
143 x
. attributes
[ "protocol-version" ] = "1.0"
144 x
. attributes
[ "config-ns" ] = legacy
. url
+ "/component"
147 def componentDisconnected ( self
):
149 self
. xmlstream
= None
151 def onRouteMessage ( self
, el
):
152 for child
in el
. elements ():
153 if child
. name
== "message" :
154 self
. onMessage ( child
)
155 elif child
. name
== "presence" :
156 # Ignore any presence broadcasts about other XCP components
157 if child
. getAttribute ( "to" ) and child
. getAttribute ( "to" ). find ( "@-internal" ) > 0 : return
158 self
. onPresence ( child
)
159 elif child
. name
== "iq" :
160 self
. discovery
. onIq ( child
)
162 def onMessage ( self
, el
):
163 fro
= el
. getAttribute ( "from" )
165 froj
= jid
. intern ( fro
)
167 LogEvent ( WARN
, "" , "Failed stringprep." )
169 mtype
= el
. getAttribute ( "type" )
170 if self
. sessions
. has_key ( froj
. userhost ()):
171 self
. sessions
[ froj
. userhost ()]. onMessage ( el
)
172 elif mtype
!= "error" :
173 to
= el
. getAttribute ( "to" )
174 ulang
= utils
. getLang ( el
)
176 for child
in el
. elements ():
177 if child
. name
== "body" :
178 body
= child
.__ str
__ ()
179 LogEvent ( INFO
, "" , "Sending error response to a message outside of session." )
180 jabw
. sendErrorMessage ( self
, fro
, to
, "auth" , "not-authorized" , lang
. get ( ulang
). notLoggedIn
, body
)
182 def onPresence ( self
, el
):
183 fro
= el
. getAttribute ( "from" )
184 to
= el
. getAttribute ( "to" )
186 froj
= jid
. intern ( fro
)
189 LogEvent ( WARN
, "" , "Failed stringprep." )
192 if self
. sessions
. has_key ( froj
. userhost ()):
193 self
. sessions
[ froj
. userhost ()]. onPresence ( el
)
195 ulang
= utils
. getLang ( el
)
196 ptype
= el
. getAttribute ( "type" )
198 # If the presence packet is to the transport (not a user) and there isn't already a session
199 if not el
. getAttribute ( "type" ): # Don't create a session unless they're sending available presence
200 LogEvent ( INFO
, "" , "Attempting to create a new session." )
201 s
= session
. makeSession ( self
, froj
. userhost (), ulang
)
203 self
. statistics
. stats
[ "TotalUsers" ] += 1
204 self
. sessions
[ froj
. userhost ()] = s
205 LogEvent ( INFO
, "" , "New session created." )
206 # Send the first presence
209 LogEvent ( INFO
, "" , "Failed to create session" )
210 jabw
. sendMessage ( self
, to
= froj
. userhost (), fro
= config
. jid
, body
= lang
. get ( ulang
). notRegistered
)
212 elif el
. getAttribute ( "type" ) != "error" :
213 LogEvent ( INFO
, "" , "Sending unavailable presence to non-logged in user." )
214 pres
= Element (( None , "presence" ))
215 pres
. attributes
[ "from" ] = to
216 pres
. attributes
[ "to" ] = fro
217 pres
. attributes
[ "type" ] = "unavailable"
221 elif ptype
and ( ptype
. startswith ( "subscribe" ) or ptype
. startswith ( "unsubscribe" )):
222 # They haven't logged in, and are trying to change subscription to a user
223 # Lets log them in and then do it
224 LogEvent ( INFO
, "" , "Attempting to create a session to do subscription stuff." )
225 s
= session
. makeSession ( self
, froj
. userhost (), ulang
)
227 self
. sessions
[ froj
. userhost ()] = s
228 LogEvent ( INFO
, "" , "New session created." )
229 # Tell the session there's a new resource
230 s
. handleResourcePresence ( froj
. userhost (), froj
. resource
, toj
. userhost (), toj
. resource
, 0 , None , None , None )
231 # Send this subscription
238 if config
. compjid
: jid
= config
. compjid
239 self
. c
= component
. buildServiceManager ( jid
, config
. secret
, "tcp: %s : %s " % ( config
. mainServer
, config
. port
))
240 self
. transportSvc
= PyTransport ()
241 self
. transportSvc
. setServiceParent ( self
. c
)
242 self
. c
. startService ()
243 reactor
. addSystemEventTrigger ( 'before' , 'shutdown' , self
. shuttingDown
)
245 def alreadyRunning ( self
):
246 print "There is already a transport instance running with this configuration."
250 def shuttingDown ( self
):
251 self
. transportSvc
. removeMe ()
252 # Keep the transport running for another 3 seconds
253 def cb ( ignored
= None ):
257 reactor
. callLater ( 3.0 , d
. callback
, None )
262 def SIGHUPstuff (* args
):
263 xmlconfig
. reloadConfig ()
265 if os
. name
== "posix" :
267 # Set SIGHUP to reload the config file & close & open debug file
268 signal
. signal ( signal
. SIGHUP
, SIGHUPstuff
)
271 if __name__
== "__main__" :