PageRenderTime 41ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/module/_socket/interp_socket.py

https://bitbucket.org/dac_io/pypy
Python | 529 lines | 422 code | 19 blank | 88 comment | 27 complexity | 0f163ce06be14198cb3da7ccdfcd6a03 MD5 | raw file
  1. from pypy.interpreter.baseobjspace import Wrappable
  2. from pypy.interpreter.typedef import TypeDef, make_weakref_descr,\
  3. interp_attrproperty
  4. from pypy.interpreter.gateway import NoneNotWrapped, interp2app, unwrap_spec
  5. from pypy.rlib.rarithmetic import intmask
  6. from pypy.rlib import rsocket
  7. from pypy.rlib.rsocket import RSocket, AF_INET, SOCK_STREAM
  8. from pypy.rlib.rsocket import SocketError, SocketErrorWithErrno
  9. from pypy.interpreter.error import OperationError, operationerrfmt
  10. from pypy.interpreter import gateway
  11. class SignalChecker:
  12. def __init__(self, space):
  13. self.space = space
  14. def check(self):
  15. self.space.getexecutioncontext().checksignals()
  16. class W_RSocket(Wrappable, RSocket):
  17. def __del__(self):
  18. self.clear_all_weakrefs()
  19. RSocket.__del__(self)
  20. def accept_w(self, space):
  21. """accept() -> (socket object, address info)
  22. Wait for an incoming connection. Return a new socket representing the
  23. connection, and the address of the client. For IP sockets, the address
  24. info is a pair (hostaddr, port).
  25. """
  26. try:
  27. sock, addr = self.accept(W_RSocket)
  28. return space.newtuple([space.wrap(sock),
  29. addr.as_object(sock.fd, space)])
  30. except SocketError, e:
  31. raise converted_error(space, e)
  32. def bind_w(self, space, w_addr):
  33. """bind(address)
  34. Bind the socket to a local address. For IP sockets, the address is a
  35. pair (host, port); the host must refer to the local host. For raw packet
  36. sockets the address is a tuple (ifname, proto [,pkttype [,hatype]])
  37. """
  38. try:
  39. self.bind(self.addr_from_object(space, w_addr))
  40. except SocketError, e:
  41. raise converted_error(space, e)
  42. def close_w(self, space):
  43. """close()
  44. Close the socket. It cannot be used after this call.
  45. """
  46. try:
  47. self.close()
  48. except SocketError, e:
  49. raise converted_error(space, e)
  50. def connect_w(self, space, w_addr):
  51. """connect(address)
  52. Connect the socket to a remote address. For IP sockets, the address
  53. is a pair (host, port).
  54. """
  55. try:
  56. self.connect(self.addr_from_object(space, w_addr))
  57. except SocketError, e:
  58. raise converted_error(space, e)
  59. def connect_ex_w(self, space, w_addr):
  60. """connect_ex(address) -> errno
  61. This is like connect(address), but returns an error code (the errno value)
  62. instead of raising an exception when an error occurs.
  63. """
  64. try:
  65. addr = self.addr_from_object(space, w_addr)
  66. except SocketError, e:
  67. raise converted_error(space, e)
  68. error = self.connect_ex(addr)
  69. return space.wrap(error)
  70. def dup_w(self, space):
  71. try:
  72. return self.dup(W_RSocket)
  73. except SocketError, e:
  74. raise converted_error(space, e)
  75. def fileno_w(self, space):
  76. """fileno() -> integer
  77. Return the integer file descriptor of the socket.
  78. """
  79. return space.wrap(intmask(self.fd))
  80. def getpeername_w(self, space):
  81. """getpeername() -> address info
  82. Return the address of the remote endpoint. For IP sockets, the address
  83. info is a pair (hostaddr, port).
  84. """
  85. try:
  86. addr = self.getpeername()
  87. return addr.as_object(self.fd, space)
  88. except SocketError, e:
  89. raise converted_error(space, e)
  90. def getsockname_w(self, space):
  91. """getsockname() -> address info
  92. Return the address of the local endpoint. For IP sockets, the address
  93. info is a pair (hostaddr, port).
  94. """
  95. try:
  96. addr = self.getsockname()
  97. return addr.as_object(self.fd, space)
  98. except SocketError, e:
  99. raise converted_error(space, e)
  100. @unwrap_spec(level=int, optname=int)
  101. def getsockopt_w(self, space, level, optname, w_buflen=NoneNotWrapped):
  102. """getsockopt(level, option[, buffersize]) -> value
  103. Get a socket option. See the Unix manual for level and option.
  104. If a nonzero buffersize argument is given, the return value is a
  105. string of that length; otherwise it is an integer.
  106. """
  107. if w_buflen is None:
  108. try:
  109. return space.wrap(self.getsockopt_int(level, optname))
  110. except SocketError, e:
  111. raise converted_error(space, e)
  112. buflen = space.int_w(w_buflen)
  113. return space.wrap(self.getsockopt(level, optname, buflen))
  114. def gettimeout_w(self, space):
  115. """gettimeout() -> timeout
  116. Returns the timeout in floating seconds associated with socket
  117. operations. A timeout of None indicates that timeouts on socket
  118. """
  119. timeout = self.gettimeout()
  120. if timeout < 0.0:
  121. return space.w_None
  122. return space.wrap(timeout)
  123. @unwrap_spec(backlog=int)
  124. def listen_w(self, space, backlog):
  125. """listen(backlog)
  126. Enable a server to accept connections. The backlog argument must be at
  127. least 1; it specifies the number of unaccepted connection that the system
  128. will allow before refusing new connections.
  129. """
  130. try:
  131. self.listen(backlog)
  132. except SocketError, e:
  133. raise converted_error(space, e)
  134. def makefile_w(self, space, w_mode="r", w_buffsize=-1):
  135. """makefile([mode[, buffersize]]) -> file object
  136. Return a regular file object corresponding to the socket.
  137. The mode and buffersize arguments are as for the built-in open() function.
  138. """
  139. return app_makefile(space, self, w_mode, w_buffsize)
  140. @unwrap_spec(buffersize='nonnegint', flags=int)
  141. def recv_w(self, space, buffersize, flags=0):
  142. """recv(buffersize[, flags]) -> data
  143. Receive up to buffersize bytes from the socket. For the optional flags
  144. argument, see the Unix manual. When no data is available, block until
  145. at least one byte is available or until the remote end is closed. When
  146. the remote end is closed and all data is read, return the empty string.
  147. """
  148. try:
  149. data = self.recv(buffersize, flags)
  150. except SocketError, e:
  151. raise converted_error(space, e)
  152. return space.wrap(data)
  153. @unwrap_spec(buffersize='nonnegint', flags=int)
  154. def recvfrom_w(self, space, buffersize, flags=0):
  155. """recvfrom(buffersize[, flags]) -> (data, address info)
  156. Like recv(buffersize, flags) but also return the sender's address info.
  157. """
  158. try:
  159. data, addr = self.recvfrom(buffersize, flags)
  160. if addr:
  161. w_addr = addr.as_object(self.fd, space)
  162. else:
  163. w_addr = space.w_None
  164. return space.newtuple([space.wrap(data), w_addr])
  165. except SocketError, e:
  166. raise converted_error(space, e)
  167. @unwrap_spec(data='bufferstr', flags=int)
  168. def send_w(self, space, data, flags=0):
  169. """send(data[, flags]) -> count
  170. Send a data string to the socket. For the optional flags
  171. argument, see the Unix manual. Return the number of bytes
  172. sent; this may be less than len(data) if the network is busy.
  173. """
  174. try:
  175. count = self.send(data, flags)
  176. except SocketError, e:
  177. raise converted_error(space, e)
  178. return space.wrap(count)
  179. @unwrap_spec(data='bufferstr', flags=int)
  180. def sendall_w(self, space, data, flags=0):
  181. """sendall(data[, flags])
  182. Send a data string to the socket. For the optional flags
  183. argument, see the Unix manual. This calls send() repeatedly
  184. until all data is sent. If an error occurs, it's impossible
  185. to tell how much data has been sent.
  186. """
  187. try:
  188. count = self.sendall(data, flags, SignalChecker(space))
  189. except SocketError, e:
  190. raise converted_error(space, e)
  191. @unwrap_spec(data='bufferstr')
  192. def sendto_w(self, space, data, w_param2, w_param3=NoneNotWrapped):
  193. """sendto(data[, flags], address) -> count
  194. Like send(data, flags) but allows specifying the destination address.
  195. For IP sockets, the address is a pair (hostaddr, port).
  196. """
  197. if w_param3 is None:
  198. # 2 args version
  199. flags = 0
  200. w_addr = w_param2
  201. else:
  202. # 3 args version
  203. flags = space.int_w(w_param2)
  204. w_addr = w_param3
  205. try:
  206. addr = self.addr_from_object(space, w_addr)
  207. count = self.sendto(data, flags, addr)
  208. except SocketError, e:
  209. raise converted_error(space, e)
  210. return space.wrap(count)
  211. @unwrap_spec(flag=bool)
  212. def setblocking_w(self, flag):
  213. """setblocking(flag)
  214. Set the socket to blocking (flag is true) or non-blocking (false).
  215. setblocking(True) is equivalent to settimeout(None);
  216. setblocking(False) is equivalent to settimeout(0.0).
  217. """
  218. self.setblocking(flag)
  219. @unwrap_spec(level=int, optname=int)
  220. def setsockopt_w(self, space, level, optname, w_optval):
  221. """setsockopt(level, option, value)
  222. Set a socket option. See the Unix manual for level and option.
  223. The value argument can either be an integer or a string.
  224. """
  225. try:
  226. optval = space.int_w(w_optval)
  227. except:
  228. optval = space.str_w(w_optval)
  229. try:
  230. self.setsockopt(level, optname, optval)
  231. except SocketError, e:
  232. raise converted_error(space, e)
  233. return
  234. try:
  235. self.setsockopt_int(level, optname, optval)
  236. except SocketError, e:
  237. raise converted_error(space, e)
  238. def settimeout_w(self, space, w_timeout):
  239. """settimeout(timeout)
  240. Set a timeout on socket operations. 'timeout' can be a float,
  241. giving in seconds, or None. Setting a timeout of None disables
  242. the timeout feature and is equivalent to setblocking(1).
  243. Setting a timeout of zero is the same as setblocking(0).
  244. """
  245. if space.is_w(w_timeout, space.w_None):
  246. timeout = -1.0
  247. else:
  248. timeout = space.float_w(w_timeout)
  249. if timeout < 0.0:
  250. raise OperationError(space.w_ValueError,
  251. space.wrap('Timeout value out of range'))
  252. self.settimeout(timeout)
  253. @unwrap_spec(nbytes=int, flags=int)
  254. def recv_into_w(self, space, w_buffer, nbytes=0, flags=0):
  255. rwbuffer = space.rwbuffer_w(w_buffer)
  256. lgt = rwbuffer.getlength()
  257. if nbytes == 0 or nbytes > lgt:
  258. nbytes = lgt
  259. try:
  260. return space.wrap(self.recvinto(rwbuffer, nbytes, flags))
  261. except SocketError, e:
  262. raise converted_error(space, e)
  263. @unwrap_spec(nbytes=int, flags=int)
  264. def recvfrom_into_w(self, space, w_buffer, nbytes=0, flags=0):
  265. rwbuffer = space.rwbuffer_w(w_buffer)
  266. lgt = rwbuffer.getlength()
  267. if nbytes == 0 or nbytes > lgt:
  268. nbytes = lgt
  269. try:
  270. readlgt, addr = self.recvfrom_into(rwbuffer, nbytes, flags)
  271. if addr:
  272. w_addr = addr.as_object(self.fd, space)
  273. else:
  274. w_addr = space.w_None
  275. return space.newtuple([space.wrap(readlgt), w_addr])
  276. except SocketError, e:
  277. raise converted_error(space, e)
  278. @unwrap_spec(cmd=int)
  279. def ioctl_w(self, space, cmd, w_option):
  280. from pypy.rpython.lltypesystem import rffi, lltype
  281. from pypy.rlib import rwin32
  282. from pypy.rlib.rsocket import _c
  283. recv_ptr = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw')
  284. try:
  285. if cmd == _c.SIO_RCVALL:
  286. value_size = rffi.sizeof(rffi.INTP)
  287. elif cmd == _c.SIO_KEEPALIVE_VALS:
  288. value_size = rffi.sizeof(_c.tcp_keepalive)
  289. else:
  290. raise operationerrfmt(space.w_ValueError,
  291. "invalid ioctl command %d", cmd)
  292. value_ptr = lltype.malloc(rffi.VOIDP.TO, value_size, flavor='raw')
  293. try:
  294. if cmd == _c.SIO_RCVALL:
  295. option_ptr = rffi.cast(rffi.INTP, value_ptr)
  296. option_ptr[0] = space.int_w(w_option)
  297. elif cmd == _c.SIO_KEEPALIVE_VALS:
  298. w_onoff, w_time, w_interval = space.unpackiterable(w_option)
  299. option_ptr = rffi.cast(lltype.Ptr(_c.tcp_keepalive), value_ptr)
  300. option_ptr.c_onoff = space.uint_w(w_onoff)
  301. option_ptr.c_keepalivetime = space.uint_w(w_time)
  302. option_ptr.c_keepaliveinterval = space.uint_w(w_interval)
  303. res = _c.WSAIoctl(
  304. self.fd, cmd, value_ptr, value_size,
  305. rffi.NULL, 0, recv_ptr, rffi.NULL, rffi.NULL)
  306. if res < 0:
  307. raise converted_error(space, rsocket.last_error())
  308. finally:
  309. if value_ptr:
  310. lltype.free(value_ptr, flavor='raw')
  311. return space.wrap(recv_ptr[0])
  312. finally:
  313. lltype.free(recv_ptr, flavor='raw')
  314. @unwrap_spec(how=int)
  315. def shutdown_w(self, space, how):
  316. """shutdown(flag)
  317. Shut down the reading side of the socket (flag == SHUT_RD), the
  318. writing side of the socket (flag == SHUT_WR), or both ends
  319. (flag == SHUT_RDWR).
  320. """
  321. try:
  322. self.shutdown(how)
  323. except SocketError, e:
  324. raise converted_error(space, e)
  325. #------------------------------------------------------------
  326. # Support functions for socket._socketobject
  327. usecount = 1
  328. def _reuse_w(self):
  329. """_resue()
  330. Increase the usecount of the socketobject.
  331. Intended only to be used by socket._socketobject
  332. """
  333. self.usecount += 1
  334. def _drop_w(self, space):
  335. """_drop()
  336. Decrease the usecount of the socketobject. If the
  337. usecount reaches 0 close the socket.
  338. Intended only to be used by socket._socketobject
  339. """
  340. self.usecount -= 1
  341. if self.usecount > 0:
  342. return
  343. self.close_w(space)
  344. app_makefile = gateway.applevel(r'''
  345. def makefile(self, mode="r", buffersize=-1):
  346. """makefile([mode[, buffersize]]) -> file object
  347. Return a regular file object corresponding to the socket.
  348. The mode and buffersize arguments are as for the built-in open() function.
  349. """
  350. import os
  351. newfd = os.dup(self.fileno())
  352. return os.fdopen(newfd, mode, buffersize)
  353. ''', filename =__file__).interphook('makefile')
  354. @unwrap_spec(family=int, type=int, proto=int)
  355. def newsocket(space, w_subtype, family=AF_INET,
  356. type=SOCK_STREAM, proto=0):
  357. # XXX If we want to support subclassing the socket type we will need
  358. # something along these lines. But allocate_instance is only defined
  359. # on the standard object space, so this is not really correct.
  360. #sock = space.allocate_instance(W_RSocket, w_subtype)
  361. #Socket.__init__(sock, space, fd, family, type, proto)
  362. try:
  363. sock = W_RSocket(family, type, proto)
  364. except SocketError, e:
  365. raise converted_error(space, e)
  366. return space.wrap(sock)
  367. descr_socket_new = interp2app(newsocket)
  368. # ____________________________________________________________
  369. # Error handling
  370. class SocketAPI:
  371. def __init__(self, space):
  372. self.w_error = space.new_exception_class(
  373. "_socket.error", space.w_IOError)
  374. self.w_herror = space.new_exception_class(
  375. "_socket.herror", self.w_error)
  376. self.w_gaierror = space.new_exception_class(
  377. "_socket.gaierror", self.w_error)
  378. self.w_timeout = space.new_exception_class(
  379. "_socket.timeout", self.w_error)
  380. self.errors_w = {'error': self.w_error,
  381. 'herror': self.w_herror,
  382. 'gaierror': self.w_gaierror,
  383. 'timeout': self.w_timeout,
  384. }
  385. def get_exception(self, applevelerrcls):
  386. return self.errors_w[applevelerrcls]
  387. def get_error(space, name):
  388. return space.fromcache(SocketAPI).get_exception(name)
  389. def converted_error(space, e):
  390. message = e.get_msg()
  391. w_exception_class = get_error(space, e.applevelerrcls)
  392. if isinstance(e, SocketErrorWithErrno):
  393. w_exception = space.call_function(w_exception_class, space.wrap(e.errno),
  394. space.wrap(message))
  395. else:
  396. w_exception = space.call_function(w_exception_class, space.wrap(message))
  397. return OperationError(w_exception_class, w_exception)
  398. # ____________________________________________________________
  399. socketmethodnames = """
  400. accept bind close connect connect_ex dup fileno
  401. getpeername getsockname getsockopt gettimeout listen makefile
  402. recv recvfrom send sendall sendto setblocking
  403. setsockopt settimeout shutdown _reuse _drop recv_into recvfrom_into
  404. """.split()
  405. # Remove non-implemented methods
  406. for name in ('dup',):
  407. if not hasattr(RSocket, name):
  408. socketmethodnames.remove(name)
  409. if hasattr(rsocket._c, 'WSAIoctl'):
  410. socketmethodnames.append('ioctl')
  411. socketmethods = {}
  412. for methodname in socketmethodnames:
  413. method = getattr(W_RSocket, methodname + '_w')
  414. socketmethods[methodname] = interp2app(method)
  415. W_RSocket.typedef = TypeDef("_socket.socket",
  416. __doc__ = """\
  417. socket([family[, type[, proto]]]) -> socket object
  418. Open a socket of the given type. The family argument specifies the
  419. address family; it defaults to AF_INET. The type argument specifies
  420. whether this is a stream (SOCK_STREAM, this is the default)
  421. or datagram (SOCK_DGRAM) socket. The protocol argument defaults to 0,
  422. specifying the default protocol. Keyword arguments are accepted.
  423. A socket object represents one endpoint of a network connection.
  424. Methods of socket objects (keyword arguments not allowed):
  425. accept() -- accept a connection, returning new socket and client address
  426. bind(addr) -- bind the socket to a local address
  427. close() -- close the socket
  428. connect(addr) -- connect the socket to a remote address
  429. connect_ex(addr) -- connect, return an error code instead of an exception
  430. dup() -- return a new socket object identical to the current one [*]
  431. fileno() -- return underlying file descriptor
  432. getpeername() -- return remote address [*]
  433. getsockname() -- return local address
  434. getsockopt(level, optname[, buflen]) -- get socket options
  435. gettimeout() -- return timeout or None
  436. listen(n) -- start listening for incoming connections
  437. makefile([mode, [bufsize]]) -- return a file object for the socket [*]
  438. recv(buflen[, flags]) -- receive data
  439. recvfrom(buflen[, flags]) -- receive data and sender's address
  440. sendall(data[, flags]) -- send all data
  441. send(data[, flags]) -- send data, may not send all of it
  442. sendto(data[, flags], addr) -- send data to a given address
  443. setblocking(0 | 1) -- set or clear the blocking I/O flag
  444. setsockopt(level, optname, value) -- set socket options
  445. settimeout(None | float) -- set or clear the timeout
  446. shutdown(how) -- shut down traffic in one or both directions
  447. [*] not available on all platforms!""",
  448. __new__ = descr_socket_new,
  449. __weakref__ = make_weakref_descr(W_RSocket),
  450. type = interp_attrproperty('type', W_RSocket),
  451. proto = interp_attrproperty('proto', W_RSocket),
  452. family = interp_attrproperty('family', W_RSocket),
  453. ** socketmethods
  454. )