chiark / gitweb /
sel-timer: Pyrex now wants explicit truncations to integer.
[mLib-python] / ident.pyx
1 # -*-pyrex-*-
2 #
3 # $Id$
4 #
5 # Ident client
6 #
7 # (c) 2005 Straylight/Edgeware
8 #
9
10 #----- Licensing notice -----------------------------------------------------
11 #
12 # This file is part of the Python interface to mLib.
13 #
14 # mLib/Python is free software; you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation; either version 2 of the License, or
17 # (at your option) any later version.
18 #
19 # mLib/Python is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 # GNU General Public License for more details.
23 #
24 # You should have received a copy of the GNU General Public License
25 # along with mLib/Python; if not, write to the Free Software Foundation,
26 # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27
28 import socket
29
30 cdef _inaddr_frompy(sockaddr_in *sin, addr):
31   cdef int port
32   if len(addr) != 2:
33     raise TypeError, 'want address/port pair'
34   a = addr[0]
35   if not inet_aton(a, &sin.sin_addr):
36     raise TypeError, 'bad IP address'
37   port = addr[1]
38   if not (0 <= port < 65536):
39     raise TypeError, 'port number out of range'
40   sin.sin_port = htons(port)
41
42 cdef _inaddr_topy(sockaddr_in *sin):
43   return inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)
44
45 cdef class SelIdentify:
46   cdef ident_request irq
47   cdef int _activep
48   cdef readonly localaddr
49   cdef readonly remoteaddr
50   cdef _user
51   cdef _bad
52   cdef _error
53   cdef _failed
54   cdef _bogus
55   def __new__(me, sk,
56               userproc = None, bogusproc = None,
57               badproc = None, errorproc = None, failedproc = None,
58               *hunoz, **hukairz):
59     cdef sockaddr_in s_in, s_out
60     cdef size_t sz_in, sz_out
61     cdef int fd
62     if PyObject_TypeCheck(sk, socket.SocketType):
63       fd = sk.fileno()
64       sz_in = PSIZEOF(&s_in)
65       sz_out = PSIZEOF(&s_out)
66       if getsockname(fd, <sockaddr *>&s_in, &sz_in) or \
67          getpeername(fd, <sockaddr *>&s_out, &sz_out):
68         _oserror()
69       if s_in.sin_family != AF_INET or s_out.sin_family != AF_INET:
70         raise TypeError, 'must be internet socket'
71     elif len(sk) != 2:
72       raise TypeError, 'want pair of addresses'
73     else:
74       _inaddr_frompy(&s_in, sk[0])
75       _inaddr_frompy(&s_out, sk[1])
76     ident(&me.irq, &_sel, &s_in, &s_out, _identfunc, <void *>me)
77     me.localaddr = _inaddr_topy(&s_in)
78     me.remoteaddr = _inaddr_topy(&s_out)
79     me._activep = 1
80     me._user = _checkcallable(userproc, 'user proc')
81     me._bad = _checkcallable(badproc, 'bad proc')
82     me._error = _checkcallable(errorproc, 'error proc')
83     me._failed = _checkcallable(failedproc, 'failed proc')
84     me._bogus = _checkcallable(bogusproc, 'bogus proc')
85   def __dealloc__(me):
86     if me._activep:
87       ident_abort(&me.irq)
88   property activep:
89     def __get__(me):
90       return _tobool(me._activep)
91   property userproc:
92     def __get__(me):
93       return me._user
94     def __set__(me, proc):
95       me._user = _checkcallable(proc, 'user proc')
96     def __del__(me):
97       me._user = None
98   property eofproc:
99     def __get__(me):
100       return me._eof
101     def __set__(me, proc):
102       me._eof = _checkcallable(proc, 'eof proc')
103     def __del__(me):
104       me._eof = None
105   property badproc:
106     def __get__(me):
107       return me._bad
108     def __set__(me, proc):
109       me._bad = _checkcallable(proc, 'bad proc')
110     def __del__(me):
111       me._bad = None
112   property errorproc:
113     def __get__(me):
114       return me._error
115     def __set__(me, proc):
116       me._error = _checkcallable(proc, 'error proc')
117     def __del__(me):
118       me._error = None
119   property failedproc:
120     def __get__(me):
121       return me._failed
122     def __set__(me, proc):
123       me._failed = _checkcallable(proc, 'failed proc')
124     def __del__(me):
125       me._failed = None
126   property bogusproc:
127     def __get__(me):
128       return me._bogus
129     def __set__(me, proc):
130       me._bogus = _checkcallable(proc, 'bogus proc')
131     def __del__(me):
132       me._bogus = None
133   def kill(me):
134     if not me._activep:
135       raise ValueError, 'already disabled'
136     ident_abort(&me.irq)
137     me._dead()
138   def _dead(me):
139     me._activep = 0
140     me.dead()
141   def dead(me):
142     pass
143   def user(me, os, user):
144     return _maybecall(me._user, (os, user))
145   def bad(me):
146     if me._bad is not None:
147       return me._bad()
148     return me.bogus()
149   def error(me, error):
150     if me._error is not None:
151       return me._error(error)
152     return me.bogus()
153   def failed(me, errno, strerror):
154     if me._failed is not None:
155       return me._failed(errno, strerror)
156     return me.bogus()
157   def bogus(me):
158     return _maybecall(me._bogus, ())
159
160 cdef void _identfunc(ident_reply *i, void *arg):
161   cdef SelIdentify id
162   id = <SelIdentify>arg
163   id._dead()
164   if i.type == IDENT_BAD:
165     id.bad()
166   elif i.type == IDENT_ERROR:
167     id.error(i.u.error)
168   elif i.type == IDENT_USERID:
169     id.user(i.u.userid.os, i.u.userid.user)
170
171 #----- That's all, folks ----------------------------------------------------