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