def READ(self, size): from rpython.rlib._rsocket_rffi import socketrecv, geterrno with rffi.scoped_alloc_buffer(size) as buf: length = socketrecv(self.fd, buf.raw, buf.size, 0) if length < 0: raise WindowsError(geterrno(), "recv") return buf.str(length)
def poll(fddict, timeout=-1): """'fddict' maps file descriptors to interesting events. 'timeout' is an integer in milliseconds, and NOT a float number of seconds, but it's the same in CPython. Use -1 for infinite. Returns a list [(fd, events)]. """ numfd = len(fddict) pollfds = lltype.malloc(_c.pollfdarray, numfd, flavor='raw') try: i = 0 for fd, events in fddict.iteritems(): rffi.setintfield(pollfds[i], 'c_fd', fd) rffi.setintfield(pollfds[i], 'c_events', events) i += 1 assert i == numfd ret = _c.poll(pollfds, numfd, timeout) if ret < 0: raise PollError(_c.geterrno()) retval = [] for i in range(numfd): pollfd = pollfds[i] fd = rffi.cast(lltype.Signed, pollfd.c_fd) revents = rffi.cast(lltype.Signed, pollfd.c_revents) if revents: retval.append((fd, revents)) finally: lltype.free(pollfds, flavor='raw') return retval
def getWindowsError(space): errno = geterrno() message = rwin32.FormatErrorW(errno) w_errcode = space.newint(errno) return OperationError(space.w_WindowsError, space.newtuple([w_errcode, space.newtext(*message), space.w_None, w_errcode]))
def _call_select(space, iwtd_w, owtd_w, ewtd_w, ll_inl, ll_outl, ll_errl, ll_timeval): fdlistin = fdlistout = fdlisterr = None nfds = -1 if ll_inl: fdlistin, nfds = _build_fd_set(space, iwtd_w, ll_inl, nfds) if ll_outl: fdlistout, nfds = _build_fd_set(space, owtd_w, ll_outl, nfds) if ll_errl: fdlisterr, nfds = _build_fd_set(space, ewtd_w, ll_errl, nfds) res = _c.select(nfds + 1, ll_inl, ll_outl, ll_errl, ll_timeval) if res < 0: errno = _c.geterrno() msg = _c.socket_strerror_str(errno) w_errortype = space.fromcache(Cache).w_error raise OperationError(w_errortype, space.newtuple([space.wrap(errno), space.wrap(msg)])) resin_w = [] resout_w = [] reserr_w = [] if res > 0: if fdlistin is not None: _unbuild_fd_set(space, iwtd_w, fdlistin, ll_inl, resin_w) if fdlistout is not None: _unbuild_fd_set(space, owtd_w, fdlistout, ll_outl, resout_w) if fdlisterr is not None: _unbuild_fd_set(space, ewtd_w, fdlisterr, ll_errl, reserr_w) return space.newtuple([space.newlist(resin_w), space.newlist(resout_w), space.newlist(reserr_w)])
def _call_select(space, iwtd_w, owtd_w, ewtd_w, ll_inl, ll_outl, ll_errl, ll_timeval): fdlistin = fdlistout = fdlisterr = None nfds = -1 if ll_inl: fdlistin, nfds = _build_fd_set(space, iwtd_w, ll_inl, nfds) if ll_outl: fdlistout, nfds = _build_fd_set(space, owtd_w, ll_outl, nfds) if ll_errl: fdlisterr, nfds = _build_fd_set(space, ewtd_w, ll_errl, nfds) res = _c.select(nfds + 1, ll_inl, ll_outl, ll_errl, ll_timeval) if res < 0: errno = _c.geterrno() msg = _c.socket_strerror_str(errno) w_errortype = space.fromcache(Cache).w_error raise OperationError(w_errortype, space.newtuple([ space.newint(errno), space.newtext(msg)])) resin_w = [] resout_w = [] reserr_w = [] if res > 0: if fdlistin is not None: _unbuild_fd_set(space, iwtd_w, fdlistin, ll_inl, resin_w) if fdlistout is not None: _unbuild_fd_set(space, owtd_w, fdlistout, ll_outl, resout_w) if fdlisterr is not None: _unbuild_fd_set(space, ewtd_w, fdlisterr, ll_errl, reserr_w) return space.newtuple([space.newlist(resin_w), space.newlist(resout_w), space.newlist(reserr_w)])
def _connect(self, address): """Connect the socket to a remote address.""" addr = address.lock() res = _c.socketconnect(self.fd, addr, address.addrlen) address.unlock() errno = _c.geterrno() timeout = self.timeout if timeout > 0.0 and res < 0 and errno == _c.EWOULDBLOCK: tv = rffi.make(_c.timeval) rffi.setintfield(tv, 'c_tv_sec', int(timeout)) rffi.setintfield(tv, 'c_tv_usec', int((timeout-int(timeout)) * 1000000)) fds = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(fds) _c.FD_SET(self.fd, fds) fds_exc = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(fds_exc) _c.FD_SET(self.fd, fds_exc) null = lltype.nullptr(_c.fd_set.TO) try: n = _c.select(self.fd + 1, null, fds, fds_exc, tv) if n > 0: if _c.FD_ISSET(self.fd, fds): # socket writable == connected return (0, False) else: # per MS docs, call getsockopt() to get error assert _c.FD_ISSET(self.fd, fds_exc) return (self.getsockopt_int(_c.SOL_SOCKET, _c.SO_ERROR), False) elif n == 0: return (_c.EWOULDBLOCK, True) else: return (_c.geterrno(), False) finally: lltype.free(fds, flavor='raw') lltype.free(fds_exc, flavor='raw') lltype.free(tv, flavor='raw') if res == 0: errno = 0 return (errno, False)
def select(inl, outl, excl, timeout=-1.0): nfds = 0 if inl: ll_inl = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(ll_inl) for i in inl: _c.FD_SET(i, ll_inl) if i > nfds: nfds = i else: ll_inl = lltype.nullptr(_c.fd_set.TO) if outl: ll_outl = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(ll_outl) for i in outl: _c.FD_SET(i, ll_outl) if i > nfds: nfds = i else: ll_outl = lltype.nullptr(_c.fd_set.TO) if excl: ll_excl = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(ll_excl) for i in excl: _c.FD_SET(i, ll_excl) if i > nfds: nfds = i else: ll_excl = lltype.nullptr(_c.fd_set.TO) if timeout != -1.0: ll_timeval = rffi.make(_c.timeval) rffi.setintfield(ll_timeval, 'c_tv_sec', int(timeout)) rffi.setintfield(ll_timeval, 'c_tv_usec', int((timeout-int(timeout)) * 1000000)) else: ll_timeval = lltype.nullptr(_c.timeval) try: res = _c.select(nfds + 1, ll_inl, ll_outl, ll_excl, ll_timeval) if res == -1: raise SelectError(_c.geterrno()) if res == 0: return ([], [], []) else: return ( [i for i in inl if _c.FD_ISSET(i, ll_inl)], [i for i in outl if _c.FD_ISSET(i, ll_outl)], [i for i in excl if _c.FD_ISSET(i, ll_excl)]) finally: if ll_inl: lltype.free(ll_inl, flavor='raw') if ll_outl: lltype.free(ll_outl, flavor='raw') if ll_excl: lltype.free(ll_excl, flavor='raw') if ll_timeval: lltype.free(ll_timeval, flavor='raw')
def _call_select(space, iwtd_w, owtd_w, ewtd_w, ll_inl, ll_outl, ll_errl, ll_timeval, timeout): fdlistin = fdlistout = fdlisterr = None nfds = -1 if ll_inl: fdlistin, nfds = _build_fd_set(space, iwtd_w, ll_inl, nfds) if ll_outl: fdlistout, nfds = _build_fd_set(space, owtd_w, ll_outl, nfds) if ll_errl: fdlisterr, nfds = _build_fd_set(space, ewtd_w, ll_errl, nfds) if ll_timeval: end_time = timeutils.monotonic(space) + timeout else: end_time = 0.0 while True: if ll_timeval: i = int(timeout) rffi.setintfield(ll_timeval, 'c_tv_sec', i) rffi.setintfield(ll_timeval, 'c_tv_usec', int((timeout - i) * 1000000)) res = _c.select(nfds + 1, ll_inl, ll_outl, ll_errl, ll_timeval) if res >= 0: break # normal path err = _c.geterrno() if err != errno.EINTR: msg = _c.socket_strerror_unicode(err) raise OperationError( space.w_OSError, space.newtuple([space.newint(err), space.newunicode(msg)])) # got EINTR, automatic retry space.getexecutioncontext().checksignals() if timeout > 0.0: timeout = end_time - timeutils.monotonic(space) if timeout < 0.0: timeout = 0.0 resin_w = [] resout_w = [] reserr_w = [] if res > 0: if fdlistin is not None: _unbuild_fd_set(space, iwtd_w, fdlistin, ll_inl, resin_w) if fdlistout is not None: _unbuild_fd_set(space, owtd_w, fdlistout, ll_outl, resout_w) if fdlisterr is not None: _unbuild_fd_set(space, ewtd_w, fdlisterr, ll_errl, reserr_w) return space.newtuple([ space.newlist(resin_w), space.newlist(resout_w), space.newlist(reserr_w) ])
def _connect(self, address): """Connect the socket to a remote address.""" addr = address.lock() res = _c.socketconnect(self.fd, addr, address.addrlen) address.unlock() errno = _c.geterrno() if self.timeout > 0.0 and res < 0 and errno == _c.EINPROGRESS: timeout = self._select(True) if timeout == 0: res = self.getsockopt_int(_c.SOL_SOCKET, _c.SO_ERROR) if res == _c.EISCONN: res = 0 errno = res elif timeout == -1: return (_c.geterrno(), False) else: return (_c.EWOULDBLOCK, True) if res < 0: res = errno return (res, False)
def last_error(): return CSocketError(_c.geterrno())
def WRITE(self, data): from rpython.rlib._rsocket_rffi import send, geterrno length = send(self.fd, data, len(data), 0) if length < 0: raise WindowsError(geterrno(), "send") return length
def select(inl, outl, excl, timeout=-1.0, handle_eintr=False): nfds = 0 if inl: ll_inl = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(ll_inl) for i in inl: _c.FD_SET(i, ll_inl) if i > nfds: nfds = i else: ll_inl = lltype.nullptr(_c.fd_set.TO) if outl: ll_outl = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(ll_outl) for i in outl: _c.FD_SET(i, ll_outl) if i > nfds: nfds = i else: ll_outl = lltype.nullptr(_c.fd_set.TO) if excl: ll_excl = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(ll_excl) for i in excl: _c.FD_SET(i, ll_excl) if i > nfds: nfds = i else: ll_excl = lltype.nullptr(_c.fd_set.TO) if timeout < 0: ll_timeval = lltype.nullptr(_c.timeval) while True: res = _c.select(nfds + 1, ll_inl, ll_outl, ll_excl, ll_timeval) if not handle_eintr or res >= 0 or _c.geterrno() != EINTR: break else: sec = int(timeout) usec = int((timeout - sec) * 10**6) ll_timeval = rffi.make(_c.timeval) rffi.setintfield(ll_timeval, 'c_tv_sec', sec) rffi.setintfield(ll_timeval, 'c_tv_usec', usec) res = _c.select(nfds + 1, ll_inl, ll_outl, ll_excl, ll_timeval) if handle_eintr and res < 0 and _c.geterrno() == EINTR: res = 0 # interrupted, act as timed out try: if res == -1: raise SelectError(_c.geterrno()) if res == 0: return ([], [], []) else: return ([i for i in inl if _c.FD_ISSET(i, ll_inl) ], [i for i in outl if _c.FD_ISSET(i, ll_outl)], [i for i in excl if _c.FD_ISSET(i, ll_excl)]) finally: if ll_inl: lltype.free(ll_inl, flavor='raw') if ll_outl: lltype.free(ll_outl, flavor='raw') if ll_excl: lltype.free(ll_excl, flavor='raw') if ll_timeval: lltype.free(ll_timeval, flavor='raw')
def poll(fddict, timeout=-1): """'fddict' maps file descriptors to interesting events. 'timeout' is an integer in milliseconds, and NOT a float number of seconds, but it's the same in CPython. Use -1 for infinite. Returns a list [(fd, events)]. """ numfd = len(fddict) numevents = 0 socketevents = lltype.malloc(_c.WSAEVENT_ARRAY, numfd, flavor='raw') try: eventdict = {} for fd, events in fddict.iteritems(): # select desired events wsaEvents = 0 if events & _c.POLLIN: wsaEvents |= _c.FD_READ | _c.FD_ACCEPT | _c.FD_CLOSE if events & _c.POLLOUT: wsaEvents |= _c.FD_WRITE | _c.FD_CONNECT | _c.FD_CLOSE # if no events then ignore socket if wsaEvents == 0: continue # select socket for desired events event = _c.WSACreateEvent() if _c.WSAEventSelect(fd, event, wsaEvents) != 0: raise PollError(_c.geterrno()) eventdict[fd] = event socketevents[numevents] = event numevents += 1 assert numevents <= numfd # if no sockets then return immediately # XXX commented out by arigo - we just want to sleep for # 'timeout' milliseconds in this case, which is what # I hope WSAWaitForMultipleEvents will do, no? #if numevents == 0: # return [] # prepare timeout if timeout < 0: timeout = _c.INFINITE ret = _c.WSAWaitForMultipleEvents(numevents, socketevents, False, timeout, False) if ret == _c.WSA_WAIT_TIMEOUT: return [] if ret == r_uint(_c.WSA_WAIT_FAILED): raise PollError(_c.geterrno()) retval = [] info = rffi.make(_c.WSANETWORKEVENTS) for fd, event in eventdict.iteritems(): if _c.WSAEnumNetworkEvents(fd, event, info) < 0: continue revents = 0 if info.c_lNetworkEvents & _c.FD_READ: revents |= _c.POLLIN if info.c_lNetworkEvents & _c.FD_ACCEPT: revents |= _c.POLLIN if info.c_lNetworkEvents & _c.FD_WRITE: revents |= _c.POLLOUT if info.c_lNetworkEvents & _c.FD_CONNECT: if info.c_iErrorCode[_c.FD_CONNECT_BIT]: revents |= _c.POLLERR else: revents |= _c.POLLOUT if info.c_lNetworkEvents & _c.FD_CLOSE: if info.c_iErrorCode[_c.FD_CLOSE_BIT]: revents |= _c.POLLERR else: if fddict[fd] & _c.POLLIN: revents |= _c.POLLIN if fddict[fd] & _c.POLLOUT: revents |= _c.POLLOUT if revents: retval.append((fd, revents)) lltype.free(info, flavor='raw') finally: for fd, event in eventdict.iteritems(): _c.WSAEventSelect(fd, event, 0) _c.WSACloseEvent(event) lltype.free(socketevents, flavor='raw') return retval
def _poll(fddict, timeout=-1): """'fddict' maps file descriptors to interesting events. 'timeout' is an integer in milliseconds, and NOT a float number of seconds, but it's the same in CPython. Use -1 for infinite. Returns a list [(fd, events)]. """ numfd = len(fddict) numevents = 0 socketevents = lltype.malloc(_c.WSAEVENT_ARRAY, numfd, flavor='raw') try: eventdict = {} for fd, events in fddict.iteritems(): # select desired events wsaEvents = 0 if events & _c.POLLIN: wsaEvents |= _c.FD_READ | _c.FD_ACCEPT | _c.FD_CLOSE if events & _c.POLLOUT: wsaEvents |= _c.FD_WRITE | _c.FD_CONNECT | _c.FD_CLOSE # if no events then ignore socket if wsaEvents == 0: continue # select socket for desired events event = _c.WSACreateEvent() if _c.WSAEventSelect(fd, event, wsaEvents) != 0: raise PollError(_c.geterrno()) eventdict[fd] = event socketevents[numevents] = event numevents += 1 assert numevents <= numfd # if no sockets then return immediately # XXX commented out by arigo - we just want to sleep for # 'timeout' milliseconds in this case, which is what # I hope WSAWaitForMultipleEvents will do, no? #if numevents == 0: # return [] # prepare timeout if timeout < 0: timeout = _c.INFINITE # XXX does not correctly report write status of a port ret = _c.WSAWaitForMultipleEvents(numevents, socketevents, False, timeout, False) if ret == _c.WSA_WAIT_TIMEOUT: return [] if ret == r_uint(_c.WSA_WAIT_FAILED): raise PollError(_c.geterrno()) retval = [] info = rffi.make(_c.WSANETWORKEVENTS) for fd, event in eventdict.iteritems(): if _c.WSAEnumNetworkEvents(fd, event, info) < 0: continue revents = 0 if info.c_lNetworkEvents & _c.FD_READ: revents |= _c.POLLIN if info.c_lNetworkEvents & _c.FD_ACCEPT: revents |= _c.POLLIN if info.c_lNetworkEvents & _c.FD_WRITE: revents |= _c.POLLOUT if info.c_lNetworkEvents & _c.FD_CONNECT: if info.c_iErrorCode[_c.FD_CONNECT_BIT]: revents |= _c.POLLERR else: revents |= _c.POLLOUT if info.c_lNetworkEvents & _c.FD_CLOSE: if info.c_iErrorCode[_c.FD_CLOSE_BIT]: revents |= _c.POLLERR else: if fddict[fd] & _c.POLLIN: revents |= _c.POLLIN if fddict[fd] & _c.POLLOUT: revents |= _c.POLLOUT if revents: retval.append((fd, revents)) lltype.free(info, flavor='raw') finally: for fd, event in eventdict.iteritems(): _c.WSAEventSelect(fd, event, 0) _c.WSACloseEvent(event) lltype.free(socketevents, flavor='raw') return retval
def select(inl, outl, excl, timeout=-1.0, handle_eintr=False): nfds = 0 if inl: ll_inl = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(ll_inl) for i in inl: _c.FD_SET(i, ll_inl) if i > nfds: nfds = i else: ll_inl = lltype.nullptr(_c.fd_set.TO) if outl: ll_outl = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(ll_outl) for i in outl: _c.FD_SET(i, ll_outl) if i > nfds: nfds = i else: ll_outl = lltype.nullptr(_c.fd_set.TO) if excl: ll_excl = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(ll_excl) for i in excl: _c.FD_SET(i, ll_excl) if i > nfds: nfds = i else: ll_excl = lltype.nullptr(_c.fd_set.TO) if timeout < 0: ll_timeval = lltype.nullptr(_c.timeval) while True: res = _c.select(nfds + 1, ll_inl, ll_outl, ll_excl, ll_timeval) if not handle_eintr or res >= 0 or _c.geterrno() != EINTR: break else: sec = int(timeout) usec = int((timeout - sec) * 10**6) ll_timeval = rffi.make(_c.timeval) rffi.setintfield(ll_timeval, 'c_tv_sec', sec) rffi.setintfield(ll_timeval, 'c_tv_usec', usec) res = _c.select(nfds + 1, ll_inl, ll_outl, ll_excl, ll_timeval) if handle_eintr and res < 0 and _c.geterrno() == EINTR: res = 0 # interrupted, act as timed out try: if res == -1: raise SelectError(_c.geterrno()) if res == 0: return ([], [], []) else: return ( [i for i in inl if _c.FD_ISSET(i, ll_inl)], [i for i in outl if _c.FD_ISSET(i, ll_outl)], [i for i in excl if _c.FD_ISSET(i, ll_excl)]) finally: if ll_inl: lltype.free(ll_inl, flavor='raw') if ll_outl: lltype.free(ll_outl, flavor='raw') if ll_excl: lltype.free(ll_excl, flavor='raw') if ll_timeval: lltype.free(ll_timeval, flavor='raw')