def testComparable(self): overlapped = pywintypes.OVERLAPPED() self.assertEqual(overlapped, overlapped) # ensure we explicitly test the operators. self.assertTrue(overlapped == overlapped) self.assertFalse(overlapped != overlapped)
def testHashable(self): overlapped = pywintypes.OVERLAPPED() d = {} d[overlapped] = "hello" self.failUnlessEqual(d[overlapped], "hello")
def log(self, level, message, raiseException=False, formatArgs=[], formatKwargs={}): ''' Log a message with the given level. :param level: The log level of this message. :param message: The message to log. :param raiseException: True raises an exception if any error occurs. \ False suppresses exceptions. :type raiseException: bool ''' if (level > self.__messageSubjectLevel and level > self.__consoleLevel and level > self.__fileLevel and level > self.__syslogLevel and not self.univentionLogger_priv): return def formatMessage(unformattedMessage, removeConfidential=False): tempMessage = unicode(unformattedMessage) tempMessage = tempMessage.replace(u'%M', message) if removeConfidential: for string in self.__confidentialStrings: tempMessage = tempMessage.replace(string, u'*** confidential ***') tempMessage = tempMessage.replace(u'%D', datetime) tempMessage = tempMessage.replace(u'%T', threadId) tempMessage = tempMessage.replace(u'%l', unicode(level)) tempMessage = tempMessage.replace(u'%L', levelname) tempMessage = tempMessage.replace(u'%C', componentname) tempMessage = tempMessage.replace(u'%F', filename) tempMessage = tempMessage.replace(u'%N', linenumber) return tempMessage try: if not isinstance(message, unicode): if not isinstance(message, str): message = unicode(message) else: message = unicode(message, 'utf-8', 'replace') try: message = message.format(*formatArgs, **formatKwargs) except KeyError as e: if 'missing format for key ' not in str(e).lower(): raise e except ValueError as e: if 'invalid conversion specification' not in str(e).lower(): raise e componentname = self.__componentName datetime = unicode( time.strftime(u"%b %d %H:%M:%S", time.localtime()), 'utf-8', 'replace') threadId = unicode(thread.get_ident()) specialConfig = None try: levelname, color = _LOGLEVEL_NAME_AND_COLOR_MAPPING[level] except KeyError: levelname = u'' color = COLOR_NORMAL try: filename = unicode( os.path.basename(sys._getframe(2).f_code.co_filename)) linenumber = unicode(sys._getframe(2).f_lineno) specialConfig = self._getThreadConfig() if not specialConfig and self.__objectConfig: # Ouch, this hurts... f = sys._getframe(2) while f is not None: obj = f.f_locals.get('self') if obj: c = self._getObjectConfig(id(obj)) if c: specialConfig = c break f = f.f_back except Exception: # call stack not deep enough? try: filename except NameError: filename = u'' try: linenumber except NameError: linenumber = u'' if specialConfig: componentname = specialConfig.get('componentName', componentname) if level <= self.__messageSubjectLevel: m = self.__messageSubjectFormat if specialConfig: m = specialConfig.get('messageSubjectFormat', m) m = formatMessage(m, removeConfidential=self.__messageSubjectLevel < LOG_CONFIDENTIAL) self.__loggerSubject.setMessage(m, level) if level <= self.__consoleLevel: # Log to terminal m = self.__consoleFormat if specialConfig: m = specialConfig.get('consoleFormat', m) m = formatMessage( m, removeConfidential=self.__consoleLevel < LOG_CONFIDENTIAL) if self.__consoleStdout: fh = sys.stdout else: fh = sys.stderr try: fhEncoding = fh.encoding except Exception: fhEncoding = None if fhEncoding is None: fhEncoding = locale.getpreferredencoding() if self.__consoleColor: m = u"%s%s%s\n" % (color, m, COLOR_NORMAL) else: m = u"%s\n" % m fh.write(m.encode(fhEncoding, 'backslashreplace')) if level <= self.__fileLevel: # Log to file logFile = self.__logFile if specialConfig: logFile = specialConfig.get('logFile', logFile) if logFile: m = self.__fileFormat if specialConfig: m = specialConfig.get('fileFormat', m) m = formatMessage( m, removeConfidential=self.__fileLevel < LOG_CONFIDENTIAL) try: lf = codecs.open(logFile, 'a+', 'utf-8', 'replace') except Exception as err: lf = None if lf: timeout = 0 locked = False while not locked and timeout < 2000: # While not timed out and not locked try: # Try to lock file if os.name == 'nt': hfile = win32file._get_osfhandle( lf.fileno()) win32file.LockFileEx( hfile, win32con.LOCKFILE_EXCLUSIVE_LOCK, 0, -0x7fff0000, pywintypes.OVERLAPPED()) # win32file.LockFileEx(hfile, flags, 0, -0x10000, __overlapped) elif os.name == 'posix': # Flags for exclusive, non-blocking lock fcntl.flock(lf.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB) except IOError as err: # Locking failed # increase timeout counter, sleep 100 millis timeout += 100 time.sleep(0.1) else: # File successfully locked locked = True if locked: if self.__fileColor: m = u"%s%s%s" % (color, m, COLOR_NORMAL) m += u'\n' if os.name == 'nt': m = m.replace(u'\n', u'\r\n') lf.write(m) lf.close() if syslog is not None and level <= self.__syslogLevel: # Log to syslog m = self.__syslogFormat if specialConfig: m = specialConfig.get('syslogFormat', m) m = formatMessage( m, removeConfidential=self.__syslogLevel < LOG_CONFIDENTIAL) try: syslog.syslog(_SYSLOG_LEVEL_MAPPING[level], m) except KeyError: # No known log level - ignoring. pass if self.univentionLogger_priv: # univention log m = self.__univentionFormat if specialConfig: m = specialConfig.get('univentionFormat', m) m = formatMessage(m, removeConfidential=True) if level in (LOG_DEBUG2, LOG_DEBUG, LOG_INFO): univentionLevel = self.univentionLogger_priv.ALL elif level == LOG_NOTICE: univentionLevel = self.univentionLogger_priv.INFO elif level == LOG_WARNING: univentionLevel = self.univentionLogger_priv.WARN elif level in (LOG_ERROR, LOG_CRITICAL, LOG_COMMENT): univentionLevel = self.univentionLogger_priv.ERROR else: univentionLevel = None if univentionLevel: self.univentionLogger_priv.debug(self.__univentionClass, univentionLevel, m) except Exception as err: if raiseException: raise err
def communication_win(self, is_check): import win32event import win32file import win32api import pywintypes import winerror # event for the socket hEvent_sock = win32event.CreateEvent(None, 0, 0, None) win32file.WSAEventSelect(self.comms_socket, hEvent_sock, win32file.FD_READ) # descriptor list self.rlist = [self.comms_socket] # overlapped list self.olist = [0] # event list self.elist = [hEvent_sock] # message buffer list self.mlist = [0] # id of the read object - put in this if it was read self.ulist = [] if not self.serverorclient and self.tunnel: # client mode # objects created for the tunnel and put in the corresponding # lists hEvent_pipe = win32event.CreateEvent( None, 0, 0, None) # for reading from the pipe overlapped_pipe = pywintypes.OVERLAPPED() overlapped_pipe.hEvent = hEvent_pipe message_buffer = win32file.AllocateReadBuffer(4096) self.rlist.append(self.tunnel) self.olist.append(overlapped_pipe) self.elist.append(hEvent_pipe) self.mlist.append(message_buffer) self.ulist.append(1) while not self._stop: try: if not self.tunnel: # check or server mode without client only with socket rc = win32event.WaitForSingleObject( hEvent_sock, int(self.timeout * 1000)) if rc == winerror.WAIT_TIMEOUT: # timed out, just rerun and wait continue else: if self.ulist: # there is somebody waiting to be read for idx in self.ulist: # issueing ReadFile on all not yet read mailslots/tunnel hr, _ = win32file.ReadFile(self.rlist[idx], self.mlist[idx], self.olist[idx]) if (hr != 0) and (hr != winerror.ERROR_IO_PENDING): common.internal_print( "UDP ReadFile failed: {0}".format(hr), -1) raise self.ulist = [] # waiting to get some data somewhere rc = win32event.WaitForMultipleObjects( self.elist, 0, int(self.timeout * 1000)) if rc == winerror.WAIT_TIMEOUT: # timed out, just rerun and wait continue if rc < 0x80: # STATUS_ABANDONED_WAIT_0 if rc > 0: # the tunnel or one of the mailslots got signalled self.ulist.append(rc) if (self.olist[rc].InternalHigh < 4) or (self.mlist[rc][0:1] != "\x45"): #Only care about IPv4 continue readytogo = self.mlist[rc][0:self.olist[rc]. InternalHigh] if self.serverorclient: c = self.lookup_client_priv(readytogo) if c: self.send( common.DATA_CHANNEL_BYTE, readytogo, ((socket.inet_ntoa(c.get_public_ip_addr()), c.get_public_src_port()), None)) else: common.internal_print( "Client not found, strange?!", 0, self.verbosity, common.DEBUG) continue else: if self.authenticated: self.send(common.DATA_CHANNEL_BYTE, readytogo, (self.server_tuple, None)) if rc == 0: # socket got signalled messages = self.recv() if len(messages) == 0: continue for addr in messages: for message in messages[addr]: c = None if self.serverorclient: self.authenticated = False c = self.lookup_client_pub((addr, 0)) if common.is_control_channel(message[0:1]): if self.controlchannel.handle_control_messages( self, message[len( common.CONTROL_CHANNEL_BYTE):], (addr, None)): continue else: self.stop() break if c: self.authenticated = c.get_authenticated() if self.authenticated: try: self.packet_writer(message[ len(common.CONTROL_CHANNEL_BYTE):]) except OSError as e: print(e) except win32api.error as e: common.internal_print("UDP Exception: {0}".format(e), -1) except socket.error as se: if se.args[0] == 10054: # port is unreachable common.internal_print( "Server's port is unreachable: {0}".format(se), -1) self._stop = True return True
def __init__(self, path_handle, mode='r', share=None): """If 'path_handle' is a string, opens that file for asynchronous I/O; if it is a handle (pipe client / server, for example), sets up for asynchronous I/O. 'mode' is as per 'open' Python function, although limited to basic/common modes. """ if not _AsyncFile._notifier: _AsyncFile._notifier = asyncoro._AsyncNotifier.instance() self._asyncoro = AsynCoro.scheduler() self._overlap = pywintypes.OVERLAPPED() if isinstance(path_handle, str): self._path = path_handle if mode.startswith('r'): access = win32file.GENERIC_READ if share is None: share = win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE create = win32file.OPEN_EXISTING if '+' in mode: access |= win32file.GENERIC_WRITE elif mode.startswith('w'): access = win32file.GENERIC_WRITE if share is None: share = win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE create = win32file.CREATE_ALWAYS if '+' in mode: access |= win32file.GENERIC_READ elif mode.startswith('a'): access = win32file.GENERIC_WRITE if share is None: share = win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE create = win32file.OPEN_ALWAYS if '+' in mode: access |= win32file.GENERIC_READ # TODO: if reading, offset should be 0? sb = os.stat(path_handle) self._overlap.Offset = sb.st_size else: self._overlap = None raise ValueError('invalid mode "%s"' % mode) flags = win32file.FILE_FLAG_OVERLAPPED try: self._handle = win32file.CreateFile(path_handle, access, share, None, create, flags, None) except: self._overlap = None raise if mode.startswith('r'): flags = os.O_RDONLY elif mode.startswith('a'): flags = os.O_APPEND else: flags = 0 self._fileno = msvcrt.open_osfhandle(self._handle, flags) else: self._handle = path_handle # pipe mode should be either 'r' or 'w' flags = os.O_RDONLY if mode.startswith('r') else 0 self._fileno = msvcrt.open_osfhandle(self._handle, flags) self._buflist = [] self._read_result = None self._write_result = None self._timeout = None self._timeout_id = None _AsyncFile._notifier.register(self._handle)
def communication_win(self, is_check): # event, overlapped struct for the pipe or tunnel hEvent_pipe = win32event.CreateEvent(None, 0, 0, None) # for reading from the pipe overlapped_pipe = pywintypes.OVERLAPPED() overlapped_pipe.hEvent = hEvent_pipe # event, overlapped struct for the pipe or tunnel hEvent_rdp = win32event.CreateEvent(None, 0, 0, None) # for reading from the pipe overlapped_rdp = pywintypes.OVERLAPPED() overlapped_rdp.hEvent = hEvent_rdp # buffer for the packets message_readfile_pipe = win32file.AllocateReadBuffer(4096) message_readfile_rdp = win32file.AllocateReadBuffer(4096) # showing if we already async reading or not read_pipe = True read_rdp = False first_run = True while not self._stop: try: if not self.tunnel_r: # user is not authenticated yet, so there is no pipe # only checking the socket for data hr, _ = win32file.ReadFile(self.comms_socket, message_readfile_rdp, overlapped_rdp) if (hr == winerror.ERROR_IO_PENDING): rc = win32event.WaitForSingleObject( hEvent_rdp, int(self.timeout * 1000)) read_rdp = True else: raise rc = 0 else: # client mode so we have the socket and tunnel as well # or the client authenticated and the pipe was created if read_pipe or first_run: # no ReadFile was called before or finished, so we # are calling it again first_run = False hr, _ = win32file.ReadFile(self.tunnel_r, message_readfile_pipe, overlapped_pipe) if read_rdp: # no ReadFile was called before or finished, so we # are calling it again hr, _ = win32file.ReadFile(self.comms_socket, message_readfile_rdp, overlapped_rdp) if (hr == winerror.ERROR_IO_PENDING): # well, this was an async read, so we need to wait # until it happens rc = win32event.WaitForMultipleObjects( [hEvent_rdp, hEvent_pipe], 0, int(self.timeout * 1000)) if rc == winerror.WAIT_TIMEOUT: # timed out, just rerun and wait continue else: if hr != 0: common.internal_print( "RDP ReadFile failed: {0}".format(hr), -1) raise if rc < 0x80: # STATUS_ABANDONED_WAIT_0 if rc == 0: read_rdp = True read_pipe = False # socket got signalled # skipping header (8):length of read messages = self.recv( message_readfile_rdp[8:overlapped_rdp. InternalHigh]) # SLOW? for message in messages: # looping through the messages from socket if len(message) == 0: # this could happen when the socket died or # partial message was read. continue if common.is_control_channel(message[0:1]): # parse control messages if self.controlchannel.handle_control_messages( self, message[len(common.CONTROL_CHANNEL_BYTE ):], None): continue else: # If the module is stopped right away, then # the channel will be closing down as well. # Because of the buffering the message will # not be sent. That is why we need to sleep time.sleep(0.5) self.stop() break if self.authenticated: try: # write packet to the tunnel self.packet_writer( message[len(common.CONTROL_CHANNEL_BYTE ):]) except OSError as e: print(e) # wut? except Exception as e: if e.args[0] == 995: common.internal_print( "Interface disappered, exiting thread: {0}" .format(e), -1) self.stop() continue print(e) if rc == 1: read_rdp = False read_pipe = True # pipe/tunnel got signalled if (overlapped_pipe.InternalHigh < 4) or (message_readfile_pipe[0:1] != "\x45"): #Only care about IPv4 # too small which should not happen or not IPv4, so we just drop it. continue # reading out the packet from the buffer and discarding the rest readytogo = message_readfile_pipe[0:overlapped_pipe. InternalHigh] self.send(common.DATA_CHANNEL_BYTE, readytogo, None) except win32api.error as e: if e.args[0] == 233: # No process is on the other end of the pipe. self._stop = True common.internal_print("Client disconnected from the pipe.", -1) continue common.internal_print("RDP Exception: {0}".format(e), -1) self.cleanup() return True
def __enter__(self): self.file = open('LinkLock', 'w+') self.file_handle = win32file._get_osfhandle(self.file.fileno()) win32file.LockFileEx(self.file_handle, win32con.LOCKFILE_EXCLUSIVE_LOCK, 0, -0x10000, pywintypes.OVERLAPPED())
t = threading.Thread(target=self.connect_thread_runner, args=(False, giveup_event)) t.start() time.sleep(0.1) s2 = socket.socket() ol = pywintypes.OVERLAPPED() s2.bind(('0.0.0.0', 0)) # connectex requires the socket be bound beforehand try: win32file.ConnectEx(s2, self.addr, ol) except win32file.error, exc: win32event.SetEvent(giveup_event) if exc.winerror == 10022: # WSAEINVAL raise TestSkipped("ConnectEx is not available on this platform") raise # some error error we don't expect. win32file.GetOverlappedResult(s2.fileno(), ol, 1) ol = pywintypes.OVERLAPPED() buff = win32file.AllocateReadBuffer(1024) win32file.WSARecv(s2, buff, ol, 0) length = win32file.GetOverlappedResult(s2.fileno(), ol, 1) self.response = buff[:length] self.assertEqual(self.response, str2bytes('some expected response')) t.join(5) self.failIf(t.isAlive(), "worker thread didn't terminate") class TestTransmit(unittest.TestCase): def test_transmit(self): import binascii bytes = os.urandom(1024*1024) val = binascii.hexlify(bytes) val_length = len(val) f = tempfile.TemporaryFile()
class TestConnect(unittest.TestCase): def connect_thread_runner(self, expect_payload, giveup_event): # As Windows 2000 doesn't do ConnectEx, we need to use a non-blocking # accept, as our test connection may never come. May as well use # AcceptEx for this... listener = socket.socket() self.addr = ('localhost', random.randint(10000,64000)) listener.bind(self.addr) listener.listen(1) # create accept socket accepter = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # An overlapped overlapped = pywintypes.OVERLAPPED() overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None) # accept the connection. if expect_payload: buf_size = 1024 else: # when we don't expect data we must be careful to only pass the # exact number of bytes for the endpoint data... buf_size = win32file.CalculateSocketEndPointSize(listener) buffer = win32file.AllocateReadBuffer(buf_size) win32file.AcceptEx(listener, accepter, buffer, overlapped) # wait for the connection or our test to fail. events = giveup_event, overlapped.hEvent rc = win32event.WaitForMultipleObjects(events, False, 2000) if rc == win32event.WAIT_TIMEOUT: self.fail("timed out waiting for a connection") if rc == win32event.WAIT_OBJECT_0: # Our main thread running the test failed and will never connect. return # must be a connection. nbytes = win32file.GetOverlappedResult(listener.fileno(), overlapped, False) if expect_payload: self.request = buffer[:nbytes] accepter.send(str2bytes('some expected response')) def test_connect_with_payload(self): giveup_event = win32event.CreateEvent(None, 0, 0, None) t = threading.Thread(target=self.connect_thread_runner, args=(True, giveup_event)) t.start() time.sleep(0.1) s2 = socket.socket() ol = pywintypes.OVERLAPPED() s2.bind(('0.0.0.0', 0)) # connectex requires the socket be bound beforehand try: win32file.ConnectEx(s2, self.addr, ol, str2bytes("some expected request")) except win32file.error, exc: win32event.SetEvent(giveup_event) if exc.winerror == 10022: # WSAEINVAL raise TestSkipped("ConnectEx is not available on this platform") raise # some error error we don't expect. win32file.GetOverlappedResult(s2.fileno(), ol, 1) ol = pywintypes.OVERLAPPED() buff = win32file.AllocateReadBuffer(1024) win32file.WSARecv(s2, buff, ol, 0) length = win32file.GetOverlappedResult(s2.fileno(), ol, 1) self.response = buff[:length] self.assertEqual(self.response, str2bytes('some expected response')) self.assertEqual(self.request, str2bytes('some expected request')) t.join(5) self.failIf(t.isAlive(), "worker thread didn't terminate")
def run_windows(self): import win32file import win32event import pywintypes import winerror import win32api # creating events, overlapped structures and a buffer for reading and writing hEvent_read = win32event.CreateEvent(None, 0, 0, None) overlapped_read = pywintypes.OVERLAPPED() overlapped_read.hEvent = hEvent_read overlapped_write = pywintypes.OVERLAPPED() message = win32file.AllocateReadBuffer(4096) while not self._stop: try: # Overlapped/async read, it either blocks or returns pending hr, _ = win32file.ReadFile(self.tunnel, message, overlapped_read) if (hr == winerror.ERROR_IO_PENDING): # when the event gets signalled or timeout happens it will return rc = win32event.WaitForSingleObject( hEvent_read, int(self.timeout * 1000)) if rc == winerror.WAIT_TIMEOUT: # timed out, just rerun read continue if rc == win32event.WAIT_OBJECT_0: # read happened, packet is in "message" if (overlapped_read.InternalHigh < 4) or ( message[0:1] != "\x45"): #Only care about IPv4 # too small which should not happen or not IPv4, so we just drop it. continue # reading out the packet from the buffer and discarding the rest readytogo = message[0:overlapped_read.InternalHigh] # looking for client for c in self.clients: if c.get_private_ip_addr() == readytogo[16:20]: # client found, writing packet on client's pipe # ignoring outcome, it is async so it will happen when it will happen ;) win32file.WriteFile(c.get_pipe_w(), readytogo, overlapped_write) except win32api.error as e: if e.args[0] == 995: common.internal_print( "Interface disappered, exiting PS thread: {0}".format( e), -1) self.stop() continue if e.args[0] == 1453: common.internal_print("OS Internal error: {0}".format(e), -1) self.stop() continue common.internal_print("PS Exception: {0}".format(e), -1) return
def __init__(self, tun_dev, tun_addr, tun_remote_addr, tun_nm, tun_mtu, wsfactory): self.tun_dev = tun_dev self.tun_addr = tun_addr self.addr = tun_addr # used by mtcrypt self.tun_nm = tun_nm self.tun_mtu = int(tun_mtu) self.wsfactory = wsfactory if BSD == True: try: self.tunfd = os.open("/dev/" + tun_dev, os.O_RDWR) call([ "/sbin/ifconfig", tun_dev, tun_addr, tun_remote_addr, "up" ]) except: log.msg("Error opening TUN device. In use? Permissions?", logLevel=logging.WARN) sys.exit(ERR) reactor.addReader(self) logstr = ("Opened TUN device on %s") % (self.tun_dev) log.msg(logstr, logLevel=logging.INFO) elif LINUX == True: try: self.tun = TunTapDevice(name=tun_dev, flags=(IFF_TUN | IFF_NO_PI)) except: log.msg("Error opening TUN device. In use? Permissions?", logLevel=logging.WARN) sys.exit(ERR) self.tun.addr = tun_addr self.tun.dstaddr = tun_remote_addr self.tun.netmask = tun_nm self.tun.mtu = int(tun_mtu) self.tun.up() reactor.addReader(self) logstr = ("Opened TUN device on %s") % (self.tun.name) log.msg(logstr, logLevel=logging.INFO) elif WINDOWS == True: self.overlappedTx = pywintypes.OVERLAPPED() self.overlappedTx.hEvent = win32event.CreateEvent(None, 0, 0, None) addr_tmp = self.tun_addr.split('.') self.tun_ipv4_address = list() for i in range(0, 4): self.tun_ipv4_address.append(int(addr_tmp[i])) nm_tmp = self.tun_nm.split('.') self.tun_ipv4_netmask = list() self.tun_ipv4_network = list() for i in range(0, 4): self.tun_ipv4_netmask.append(int(nm_tmp[i])) self.tun_ipv4_network.append(int(addr_tmp[i]) & int(nm_tmp[i])) self.TAP_IOCTL_CONFIG_POINT_TO_POINT = self.TAP_CONTROL_CODE(5, 0) self.TAP_IOCTL_SET_MEDIA_STATUS = self.TAP_CONTROL_CODE(6, 0) self.TAP_IOCTL_CONFIG_TUN = self.TAP_CONTROL_CODE(10, 0) try: self.tun_handle = self.openTunTap() except: log.msg("Could not open TUN device. Permissions?", logLevel=logging.WARN) sys.exit(ERR) log.msg("Opened TUN device", logLevel=logging.INFO) self.tunRead = TunRead(self.tun_handle, self.wsfactory) self.tunRead.start()
def init_client(self, control_message, additional_data): addr = additional_data[0] client_local = client.Client() # stripping out the private IP from the message client_private_ip = control_message[0:4] # saving public IP address and port client_public_source_ip = socket.inet_aton(addr[0]) client_public_source_port = addr[1] # If this private IP is already used, the server removes that client. # For example: client reconnect on connection reset, duplicated configs # and yes, this can be used to kick somebody off the tunnel # close client related pipes for c in self.clients: # find and remove client from module's list if c.get_private_ip_addr() == client_private_ip: save_to_close = c self.clients.remove(c) if c.get_pipe_r() in self.rlist: if self.os_type == common.OS_WINDOWS: # removing client related elements from lists idx = 0 while self.rlist[idx] != c.get_pipe_r(): idx += 1 if idx < len(self.rlist): self.olist = self.olist[:idx] + self.olist[idx + 1:] self.elist = self.elist[:idx] + self.elist[idx + 1:] self.mlist = self.mlist[:idx] + self.mlist[idx + 1:] else: self.olist = self.olist[:idx] self.elist = self.elist[:idx] self.mlist = self.mlist[:idx] self.ulist.remove(idx) self.rlist.remove(c.get_pipe_r()) found = False for c in self.packetselector.get_clients(): # find and remove client from packetselector's list if c.get_private_ip_addr() == client_private_ip: found = True self.packetselector.delete_client(c) # If client was created but not added to the PacketSelector, then the # pipes still need to be closed. This could happen when the authenti- # cation fails or gets interrupted. if not found: if self.os_type == common.OS_WINDOWS: import win32file try: win32file.CloseHandle(save_to_close.get_pipe_r()) win32file.CloseHandle(save_to_close.get_pipe_w()) except: pass else: try: save_to_close.get_pipe_r_fd().close() save_to_close.get_pipe_w_fd().close() except: pass # creating new pipes for the client if self.os_type == common.OS_WINDOWS: import win32pipe import win32file import pywintypes import win32event import win32api import winerror overlapped = pywintypes.OVERLAPPED() # setting up nameslot mailslotname = "\\\\.\\mailslot\\XFLTReaT_{0}".format( socket.inet_ntoa(client_private_ip)) mailslot_r = win32file.CreateMailslot(mailslotname, 0, -1, None) if (mailslot_r == None) or (mailslot_r == win32file.INVALID_HANDLE_VALUE): internal_print("Invalid handle - mailslot", -1) sys.exit(-1) mailslot_w = win32file.CreateFile( mailslotname, win32file.GENERIC_WRITE, win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE, None, win32file.OPEN_EXISTING, win32file.FILE_ATTRIBUTE_NORMAL | win32file.FILE_FLAG_OVERLAPPED, None) if (mailslot_w == None) or (mailslot_w == win32file.INVALID_HANDLE_VALUE): internal_print("Invalid handle - readable pipe", -1) sys.exit(-1) client_local.set_pipes_fdnum(mailslot_r, mailslot_w) else: pipe_r, pipe_w = os.pipe() client_local.set_pipes_fdnum(pipe_r, pipe_w) client_local.set_pipes_fd(os.fdopen(pipe_r, "r"), os.fdopen(pipe_w, "w")) # set connection related things and authenticated to True client_local.set_public_ip_addr(client_public_source_ip) client_local.set_public_src_port(client_public_source_port) client_local.set_private_ip_addr(client_private_ip) client_local.get_encryption().set_module(self.encryption.get_module()) self.encryption = client_local.get_encryption() if self.encryption.get_module().get_step_count(): # add encryption steps self.merge_cmh(self.encryption.get_module().get_cmh_struct()) if self.authentication.get_step_count(): # add authentication steps self.merge_cmh(self.authentication.get_cmh_struct()) client_local.set_initiated(True) self.clients.append(client_local) return
hfile = win32file.CreateFile(file, win32con.GENERIC_READ | win32con.GENERIC_WRITE, win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE, secur_att, win32con.OPEN_ALWAYS, win32con.FILE_ATTRIBUTE_NORMAL, 0) ov = pywintypes.OVERLAPPED() # used to indicate starting region to lock win32file.LockFileEx(hfile, win32con.LOCKFILE_EXCLUSIVE_LOCK, 0, highbits, ov) win32api.Sleep(4000) # do something here win32file.UnlockFileEx(hfile, 0, highbits, ov) hfile.Close() # <nl > Below, I have fleshed it out with a more useable Flock class. The # code below works like this: You create an instance of the class, # providing a filename. It will create/access the file in a default way
def __win32_lock_fd(fd, timeout=None): '''returns True if the file descriptor is successfully locked''' import pywintypes import win32con import win32file import winerror try: handle = win32file._get_osfhandle(fd) if timeout is None: win32file.LockFileEx(handle, win32con.LOCKFILE_EXCLUSIVE_LOCK, 0, -0x10000, pywintypes.OVERLAPPED()) return True if timeout > 0: start = time.time() while True: try: win32file.LockFileEx(handle, win32con.LOCKFILE_EXCLUSIVE_LOCK | win32con.LOCKFILE_FAIL_IMMEDIATELY, 0, -0x10000, pywintypes.OVERLAPPED()) return True except pywintypes.error as e: if e.winerror != winerror.ERROR_LOCK_VIOLATION: break time.sleep(0.05) if time.time() > start + timeout: break else: win32file.LockFileEx(handle, win32con.LOCKFILE_EXCLUSIVE_LOCK | win32con.LOCKFILE_FAIL_IMMEDIATELY, 0, -0x10000, pywintypes.OVERLAPPED()) return True except pywintypes.error: pass return False
def pipe_server(): pipe = win32pipe.CreateNamedPipe( r'\\.\pipe\my_pipe', win32pipe.PIPE_ACCESS_INBOUND | win32file.FILE_FLAG_OVERLAPPED, win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT, 1, 65536, 65536, 0, None) quit = False overlapped_obj1 = pywintypes.OVERLAPPED() completion_port = win32file.CreateIoCompletionPort(pipe, None, 0, 0) while not quit: try: win32pipe.ConnectNamedPipe(pipe, overlapped_obj1) while True: # Doing some sleep (2 seconds): Actually, other things could be done in this time for i in range(10): time.sleep(0.2) # If the function succeeds, rc will be set to 0, otherwise it will be set to the win32 error code (258). (rc, byte_num, key, ovrlpd) = win32file.GetQueuedCompletionStatus( completion_port, 50) #1000) if rc == 0: # The message can be retrieved msg = '' # Will contain the whole message at the end """ in order to read the characters we need to distinguish two cases: -the character is a normal (unicode) character, which takes 1 byte -the character is non_unicode (German, Russian...), which takes 2 bytes as we are reading 1 byte at a time, the above-mentioned discussion is essential. When a 1 byte character is coming, its decoding is done without problems. Let's see what happens, when a 2-byte character is coming. In this case, we read 1 byte, try to decode, get an error. Now we know that the character takes 2-bytes. Then, we read 1 byte again, combine them and decode. """ # 1-byte character case try: rtnvalue, data = win32file.ReadFile( pipe, 1, overlapped_obj1) msg = msg + bytes(data).decode("utf-8") # 2-bytes character case except: rtnvalue, data1 = win32file.ReadFile( pipe, 1, overlapped_obj1) non_unicode = data.tobytes() + data1.tobytes() msg = msg + non_unicode.decode("utf-8") while rtnvalue == 234: # more data is available try: # 1-byte character case rtnvalue, data = win32file.ReadFile( pipe, 1, overlapped_obj1) msg = msg + bytes(data).decode("utf-8") except: # 2-bytes character case rtnvalue, data1 = win32file.ReadFile( pipe, 1, overlapped_obj1) non_unicode = data.tobytes() + data1.tobytes() msg = msg + non_unicode.decode("utf-8") # the next line helps with writing Russian and Armenian characters into a text file with codecs.open('test.txt', 'w', encoding='utf-8') as f: f.write(msg) f.close() print("Successfully received and written") print("Closing Handle") exit(0) except pywintypes.error as e: if e.args[0] == 109: print("broken pipe") quit = True else: print(e) quit = True win32file.CloseHandle(pipe)
def communication_win(self, is_check): import win32event import win32file import win32api import pywintypes import winerror # event for the socket hEvent_sock = win32event.CreateEvent(None, 0, 0, None) win32file.WSAEventSelect(self.comms_socket, hEvent_sock, win32file.FD_READ) # descriptor list self.rlist = [self.comms_socket] # overlapped list self.olist = [0] # event list self.elist = [hEvent_sock] # message buffer list self.mlist = [0] # id of the read object - put in this if it was read self.ulist = [] if not self.serverorclient and self.tunnel: # client mode # objects created for the tunnel and put in the corresponding # lists hEvent_pipe = win32event.CreateEvent( None, 0, 0, None) # for reading from the pipe overlapped_pipe = pywintypes.OVERLAPPED() overlapped_pipe.hEvent = hEvent_pipe message_buffer = win32file.AllocateReadBuffer(4096) self.rlist.append(self.tunnel) self.olist.append(overlapped_pipe) self.elist.append(hEvent_pipe) self.mlist.append(message_buffer) self.ulist.append(1) while not self._stop: try: if not self.tunnel: # check or server mode without client only with socket #message, addr = self.comms_socket.recvfrom(1508) rc = win32event.WaitForSingleObject( hEvent_sock, int(self.timeout * 1000)) if rc == winerror.WAIT_TIMEOUT: # timed out, just rerun and wait continue else: if self.ulist: # there is somebody waiting to be read for idx in self.ulist: # issueing ReadFile on all not yet read mailslots/tunnel hr, _ = win32file.ReadFile(self.rlist[idx], self.mlist[idx], self.olist[idx]) if (hr != 0) and (hr != winerror.ERROR_IO_PENDING): common.internal_print( "UDP ReadFile failed: {0}".format(hr), -1) raise self.ulist = [] # waiting to get some data somewhere rc = win32event.WaitForMultipleObjects( self.elist, 0, int(self.timeout * 1000)) if rc == winerror.WAIT_TIMEOUT: # timed out, just rerun and wait continue if rc < 0x80: # STATUS_ABANDONED_WAIT_0 if rc > 0: # the tunnel or one of the mailslots got signalled self.ulist.append(rc) if (self.olist[rc].InternalHigh < 4) or (self.mlist[rc][0:1] != "\x45"): #Only care about IPv4 continue readytogo = self.mlist[rc][0:self.olist[rc]. InternalHigh] if self.serverorclient: c = self.lookup_client_priv(readytogo) if c: # if the differece between the received and set sequences too big # some routers/firewalls just drop older sequences. If it gets # too big, we just drop the older ones and use the latest X packet # this helps on stabality. if (c.get_ICMP_received_sequence() - c.get_ICMP_sent_sequence() ) >= self.TRACKING_THRESHOLD: c.set_ICMP_sent_sequence( c.get_ICMP_received_sequence() - self.TRACKING_ADJUST) # get client related values: identifier and sequence number identifier = c.get_ICMP_sent_identifier() sequence = c.get_ICMP_sent_sequence() # queueing every packet first c.queue_put(readytogo) # are there any packets to answer? if (c.get_ICMP_received_sequence() - sequence) == 0: continue else: request_num = 0 # if there is less packet than that we have in the queue # then we cap the outgoing packet number if (c.get_ICMP_received_sequence() - sequence) < (c.queue_length()): number_to_get = ( c.get_ICMP_received_sequence() - sequence) else: # send all packets from the queue number_to_get = c.queue_length() for i in range(0, number_to_get): # get first packet readytogo = c.queue_get() # is it he last one we are sending now? if i == (number_to_get - 1): # if the last one and there is more in the queue # then we ask for dummy packets request_num = c.queue_length() # go packets go! self.send(common.DATA_CHANNEL_BYTE, readytogo, ((socket.inet_ntoa( c.get_public_ip_addr()), c.get_public_src_port()), identifier, sequence + i + 1, request_num)) sequence = (sequence + i + 1) % 65536 c.set_ICMP_sent_sequence(sequence) else: # there is no client with that IP common.internal_print( "Client not found, strange?!", 0, self.verbosity, common.DEBUG) continue else: if self.authenticated: # whatever we have from the tunnel, just encapsulate it # and send it out self.ICMP_sequence = (self.ICMP_sequence + 1) % 65536 self.send( common.DATA_CHANNEL_BYTE, readytogo, (self.server_tuple, self.ICMP_identifier, self.ICMP_sequence, 0)) #?? else: common.internal_print( "Spoofed packets, strange?!", 0, self.verbosity, common.DEBUG) continue if rc == 0: # socket got signalled message, addr, identifier, sequence, queue_length = self.recv( ) if len(message) == 0: continue c = None if self.serverorclient: self.authenticated = False c = self.lookup_client_pub((addr, 0)) if c: c.set_ICMP_received_identifier(identifier) # packets does not arrive in order sometime # if higher sequence arrived already, then we # do not modify # 16bit integer MAX could be a bit tricky, a # threshold had to be introduced to make it # fail safe. Hacky but should work. ICMP_THRESHOLD = 100 if (sequence > c.get_ICMP_received_sequence() ) or ((sequence < ICMP_THRESHOLD) and ((sequence + 65536) > c.get_ICMP_received_sequence()) and (c.get_ICMP_received_sequence() > ICMP_THRESHOLD)): c.set_ICMP_received_sequence(sequence) else: if queue_length: common.internal_print( "sending {0} dummy packets".format( queue_length), 0, self.verbosity, common.DEBUG) for i in range(queue_length + 10): self.ICMP_sequence = (self.ICMP_sequence + 1) % 65536 self.do_dummy_packet( self.ICMP_identifier, self.ICMP_sequence) if common.is_control_channel(message[0:1]): if self.controlchannel.handle_control_messages( self, message[len(common.CONTROL_CHANNEL_BYTE):], (addr, identifier, sequence, 0)): continue else: self.stop() break if c: self.authenticated = c.get_authenticated() if self.authenticated: try: self.packet_writer( message[len(common.CONTROL_CHANNEL_BYTE):]) except OSError as e: print(e) except win32api.error as e: common.internal_print("UDP Exception: {0}".format(e), -1) except socket.error as se: if se.args[0] == 10054: # port is unreachable common.internal_print( "Server's port is unreachable: {0}".format(se), -1) self._stop = True return True
def communication_win(self, is_check): import win32event import win32file import win32api import pywintypes import winerror # event for the socket hEvent_sock = win32event.CreateEvent(None, 0, 0, None) win32file.WSAEventSelect(self.comms_socket, hEvent_sock, win32file.FD_READ) # event, overlapped struct for the pipe or tunnel hEvent_pipe = win32event.CreateEvent(None, 0, 0, None) # for reading from the pipe overlapped_pipe = pywintypes.OVERLAPPED() overlapped_pipe.hEvent = hEvent_pipe # buffer for the packets message_readfile = win32file.AllocateReadBuffer(4096) # showing if we already async reading or not not_reading_already = True first_run = True while not self._stop: try: if not self.tunnel_r: # user is not authenticated yet, so there is no pipe # only checking the socket for data rc = win32event.WaitForSingleObject( hEvent_sock, int(self.timeout * 1000)) if rc == winerror.WAIT_TIMEOUT: # timed out, just rerun and wait continue else: # client mode so we have the socket and tunnel as well # or the client authenticated and the pipe was created if first_run or not_reading_already: # no ReadFile was called before or finished, so we # are calling it again hr, _ = win32file.ReadFile(self.tunnel_r, message_readfile, overlapped_pipe) not_reading_already = first_run = False if (hr == winerror.ERROR_IO_PENDING): # well, this was an async read, so we need to wait # until it happens rc = win32event.WaitForMultipleObjects( [hEvent_sock, hEvent_pipe], 0, int(self.timeout * 1000)) if rc == winerror.WAIT_TIMEOUT: # timed out, just rerun and wait continue else: if hr != 0: common.internal_print( "{0} ReadFile failed: {1}".format( self.module_short, hr), -1) raise if rc < 0x80: # STATUS_ABANDONED_WAIT_0 if rc == 0: # socket got signalled not_reading_already = False messages = self.recv() for message in messages: # looping through the messages from socket if len(message) == 0: # this could happen when the socket died or # partial message was read. continue if common.is_control_channel(message[0:1]): # parse control messages if self.controlchannel.handle_control_messages( self, message[len(common.CONTROL_CHANNEL_BYTE ):], None): continue else: self.stop() break if self.authenticated: try: # write packet to the tunnel self.packet_writer( message[len(common.CONTROL_CHANNEL_BYTE ):]) except OSError as e: print(e) # wut? except Exception as e: if e.args[0] == 995: common.internal_print( "Interface disappered, exiting thread: {0}" .format(e), -1) self.stop() continue if rc == 1: # pipe/tunnel got signalled not_reading_already = True if (overlapped_pipe.InternalHigh < 4) or (message_readfile[0:1] != "\x45"): #Only care about IPv4 # too small which should not happen or not IPv4, so we just drop it. continue # reading out the packet from the buffer and discarding the rest readytogo = message_readfile[0:overlapped_pipe. InternalHigh] self.send(common.DATA_CHANNEL_BYTE, readytogo, None) except win32api.error as e: common.internal_print("TCP Exception: {0}".format(e), -1) self.cleanup() return True
def testHashable(self): overlapped = pywintypes.OVERLAPPED() d = {} d[overlapped] = "hello" assert d[overlapped] == "hello"
def test_transmit(self): import binascii bytes = os.urandom(1024*1024) val = binascii.hexlify(bytes) val_length = len(val) f = tempfile.TemporaryFile() f.write(val) def runner(): s1 = socket.socket() self.addr = ('localhost', random.randint(10000,64000)) s1.bind(self.addr) s1.listen(1) cli, addr = s1.accept() buf = 1 self.request = [] while buf: buf = cli.recv(1024*100) self.request.append(buf) th = threading.Thread(target=runner) th.start() time.sleep(0.5) s2 = socket.socket() s2.connect(self.addr) length = 0 aaa = str2bytes("[AAA]") bbb = str2bytes("[BBB]") ccc = str2bytes("[CCC]") ddd = str2bytes("[DDD]") empty = str2bytes("") ol = pywintypes.OVERLAPPED() f.seek(0) win32file.TransmitFile(s2, win32file._get_osfhandle(f.fileno()), val_length, 0, ol, 0) length += win32file.GetOverlappedResult(s2.fileno(), ol, 1) ol = pywintypes.OVERLAPPED() f.seek(0) win32file.TransmitFile(s2, win32file._get_osfhandle(f.fileno()), val_length, 0, ol, 0, aaa, bbb) length += win32file.GetOverlappedResult(s2.fileno(), ol, 1) ol = pywintypes.OVERLAPPED() f.seek(0) win32file.TransmitFile(s2, win32file._get_osfhandle(f.fileno()), val_length, 0, ol, 0, empty, empty) length += win32file.GetOverlappedResult(s2.fileno(), ol, 1) ol = pywintypes.OVERLAPPED() f.seek(0) win32file.TransmitFile(s2, win32file._get_osfhandle(f.fileno()), val_length, 0, ol, 0, None, ccc) length += win32file.GetOverlappedResult(s2.fileno(), ol, 1) ol = pywintypes.OVERLAPPED() f.seek(0) win32file.TransmitFile(s2, win32file._get_osfhandle(f.fileno()), val_length, 0, ol, 0, ddd) length += win32file.GetOverlappedResult(s2.fileno(), ol, 1) s2.close() th.join() buf = str2bytes('').join(self.request) self.assertEqual(length, len(buf)) expected = val + aaa + val + bbb + val + val + ccc + ddd + val self.assertEqual(type(expected), type(buf)) self.assert_(expected == buf)
def testComparable(self): overlapped = pywintypes.OVERLAPPED() assert overlapped == overlapped # ensure we explicitly test the operators. assert overlapped == overlapped assert not (overlapped != overlapped)
def __exit__(self, type, value, traceback): win32file.UnlockFileEx(self.file_handle, 0, -0x10000, pywintypes.OVERLAPPED()) self.file.close()
def init_client(self, control_message, additional_data): self.client = client.Client() self.client.set_socket(self.comms_socket) # stripping out the private IP from the message client_private_ip = control_message[0:4] # saving public IP address and port client_public_source_ip = socket.inet_aton(self.client_addr[0]) client_public_source_port = self.client_addr[1] # If this private IP is already used, the server removes that client. # For example: client reconnect on connection reset, duplicated configs # and yes, this can be used to kick somebody off the tunnel for c in self.packetselector.get_clients(): if c.get_private_ip_addr() == client_private_ip: self.packetselector.delete_client(c) # creating new pipes for the client if self.os_type == common.OS_WINDOWS: import win32pipe import win32file import pywintypes import win32event import win32api import winerror overlapped = pywintypes.OVERLAPPED() # setting up nameslot mailslotname = "\\\\.\\mailslot\\XFLTReaT_{0}".format( socket.inet_ntoa(client_private_ip)) mailslot_r = win32file.CreateMailslot(mailslotname, 0, -1, None) if (mailslot_r == None) or (mailslot_r == win32file.INVALID_HANDLE_VALUE): internal_print("Invalid handle - mailslot", -1) sys.exit(-1) mailslot_w = win32file.CreateFile( mailslotname, win32file.GENERIC_WRITE, win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE, None, win32file.OPEN_EXISTING, win32file.FILE_ATTRIBUTE_NORMAL | win32file.FILE_FLAG_OVERLAPPED, None) if (mailslot_w == None) or (mailslot_w == win32file.INVALID_HANDLE_VALUE): internal_print("Invalid handle - readable pipe", -1) sys.exit(-1) self.client.set_pipes_fdnum(mailslot_r, mailslot_w) else: pipe_r, pipe_w = os.pipe() self.client.set_pipes_fdnum(pipe_r, pipe_w) self.client.set_pipes_fd(os.fdopen(pipe_r, "r"), os.fdopen(pipe_w, "w")) # set connection related things and authenticated to True self.client.set_public_ip_addr(client_public_source_ip) self.client.set_public_src_port(client_public_source_port) self.client.set_private_ip_addr(client_private_ip) self.client.set_stopfp(self.stop) # unifying encryption variable self.client.get_encryption().set_module(self.encryption.get_module()) self.encryption = self.client.get_encryption() if self.encryption.get_module().get_step_count(): # add encryption steps self.merge_cmh(self.encryption.get_module().get_cmh_struct()) if self.authentication.get_step_count(): # add authentication steps self.merge_cmh(self.authentication.get_cmh_struct()) self.client.set_initiated(True) return
class _Win32Opener(_Opener): """Open, lock, and unlock a file using windows primitives.""" # Error #33: # 'The process cannot access the file because another process' FILE_IN_USE_ERROR = 33 # Error #158: # 'The segment is already unlocked.' FILE_ALREADY_UNLOCKED_ERROR = 158 def open_and_lock(self, timeout, delay): """Open the file and lock it. Args: timeout: float, How long to try to lock for. delay: float, How long to wait between retries Raises: AlreadyLockedException: if the lock is already acquired. IOError: if the open fails. CredentialsFileSymbolicLinkError if the file is a symbolic link. """ if self._locked: raise AlreadyLockedException('File %s is already locked' % self._filename) start_time = time.time() validate_file(self._filename) try: self._fh = open(self._filename, self._mode) except IOError, e: # If we can't access with _mode, try _fallback_mode and don't lock. if e.errno == errno.EACCES: self._fh = open(self._filename, self._fallback_mode) return # We opened in _mode, try to lock the file. while True: try: hfile = win32file._get_osfhandle(self._fh.fileno()) win32file.LockFileEx(hfile, (win32con.LOCKFILE_FAIL_IMMEDIATELY | win32con.LOCKFILE_EXCLUSIVE_LOCK), 0, -0x10000, pywintypes.OVERLAPPED()) self._locked = True return except pywintypes.error, e: if timeout == 0: raise e # If the error is not that the file is already in use, raise. if e[0] != _Win32Opener.FILE_IN_USE_ERROR: raise # We could not acquire the lock. Try again. if (time.time() - start_time) >= timeout: logger.warn('Could not lock %s in %s seconds' % (self._filename, timeout)) if self._fh: self._fh.close() self._fh = open(self._filename, self._fallback_mode) return time.sleep(delay)
def lock(file_, flags): if flags & constants.LOCK_SH: import win32file import pywintypes import winerror __overlapped = pywintypes.OVERLAPPED() if sys.version_info.major == 2: if flags & constants.LOCK_NB: mode = constants.LOCKFILE_FAIL_IMMEDIATELY else: mode = 0 else: if flags & constants.LOCK_NB: mode = msvcrt.LK_NBRLCK else: mode = msvcrt.LK_RLCK # is there any reason not to reuse the following structure? hfile = win32file._get_osfhandle(file_.fileno()) try: win32file.LockFileEx(hfile, mode, 0, -0x10000, __overlapped) except pywintypes.error as exc_value: # error: (33, 'LockFileEx', 'The process cannot access the file # because another process has locked a portion of the file.') if exc_value.winerror == winerror.ERROR_LOCK_VIOLATION: raise exceptions.LockException( exceptions.LockException.LOCK_FAILED, exc_value.strerror, fh=file_) else: # Q: Are there exceptions/codes we should be dealing with # here? raise else: mode = constants.LOCKFILE_EXCLUSIVE_LOCK if flags & constants.LOCK_NB: mode |= constants.LOCKFILE_FAIL_IMMEDIATELY if flags & constants.LOCK_NB: mode = msvcrt.LK_NBLCK else: mode = msvcrt.LK_LOCK # windows locks byte ranges, so make sure to lock from file start try: savepos = file_.tell() if savepos: # [ ] test exclusive lock fails on seek here # [ ] test if shared lock passes this point file_.seek(0) # [x] check if 0 param locks entire file (not documented in # Python) # [x] fails with "IOError: [Errno 13] Permission denied", # but -1 seems to do the trick try: msvcrt.locking(file_.fileno(), mode, lock_length) except IOError as exc_value: # [ ] be more specific here raise exceptions.LockException( exceptions.LockException.LOCK_FAILED, exc_value.strerror, fh=file_) finally: if savepos: file_.seek(savepos) except IOError as exc_value: raise exceptions.LockException( exceptions.LockException.LOCK_FAILED, exc_value.strerror, fh=file_)
try: import win32con import win32file import pywintypes os_locking = 'windows' except: pass if os_locking == 'windows': LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK LOCK_SH = 0 # the default LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY # is there any reason not to reuse the following structure? __overlapped = pywintypes.OVERLAPPED() def lock(file, flags): hfile = win32file._get_osfhandle(file.fileno()) win32file.LockFileEx(hfile, flags, 0, 0x7fff0000, __overlapped) def unlock(file): hfile = win32file._get_osfhandle(file.fileno()) win32file.UnlockFileEx(hfile, 0, 0x7fff0000, __overlapped) elif os_locking == 'posix': LOCK_EX = fcntl.LOCK_EX LOCK_SH = fcntl.LOCK_SH LOCK_NB = fcntl.LOCK_NB
def __init__(self, args): win32serviceutil.ServiceFramework.__init__(self, args) self.hWaitStop = CreateEvent(None, 0, 0, None) self.overlapped = pywintypes.OVERLAPPED() self.overlapped.hEvent = CreateEvent(None, 0, 0, None) self.thread_handles = []
def testComparable(self): overlapped = pywintypes.OVERLAPPED() self.failUnlessEqual(overlapped, overlapped) # ensure we explicitly test the operators. self.failUnless(overlapped == overlapped) self.failIf(overlapped != overlapped)
def __init__(self, autoSetup=False): #These can be used, or not. self.myGUID = "" self.myInterface = 0 self.trimEthnHeaders = False self.ethernetMTU = 1500 self.myMACaddr = b"" self.writeDataQueue = queue.Queue() self.dataThreads = [] #Set up an overlapped structure for deviceIoControl #This originally created an array of overlapped stuctures used throughout this class, but now threads create their own for safety self.overlapped = pywintypes.OVERLAPPED() self.overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None) #Some function encapsulation #In case anyone else reads this, the tap control codes use the windows io control code interface to pass special #codes to the tap driver. Also, some constants are borrowed from the win iocontrol library (which are simply replaced with numbers here) self.TAP_IOCTL_GET_MAC = self.TAP_CONTROL_CODE(1, 0) self.TAP_IOCTL_GET_VERSION = self.TAP_CONTROL_CODE(2, 0) self.TAP_IOCTL_GET_MTU = self.TAP_CONTROL_CODE(3, 0) self.TAP_IOCTL_GET_INFO = self.TAP_CONTROL_CODE(4, 0) self.TAP_IOCTL_CONFIG_POINT_TO_POINT = self.TAP_CONTROL_CODE( 5, 0) #This call has been obsoleted, use CONFIG_TUN instead self.TAP_IOCTL_SET_MEDIA_STATUS = self.TAP_CONTROL_CODE(6, 0) self.TAP_IOCTL_CONFIG_DHCP_MASQ = self.TAP_CONTROL_CODE(7, 0) self.TAP_IOCTL_GET_LOG_LINE = self.TAP_CONTROL_CODE(8, 0) self.TAP_IOCTL_CONFIG_DHCP_SET_OPT = self.TAP_CONTROL_CODE(9, 0) self.TAP_IOCTL_CONFIG_TUN = self.TAP_CONTROL_CODE(10, 0) #Whether the object should attempt to initialize itself if autoSetup: self.myGUID = self.getDeviceGUID() #Force close if no adapter was found if not self.myGUID: alert( "Fatal error: could not locate tap adapter. (Is the adapter properly installed?) \nAutoclosing in 5 seconds.", "_all") time.sleep(5) sys.exit() alert("Tap GUID: " + self.myGUID) self.myInterface = self.createInterface() print(self.myInterface) if (self.myInterface): #Connect media, and get our MAC address self.setMediaConnectionStatus(True) self.updateMAC() else: alert( "Failed to interface with TAP adapter. Exiting in 5 seconds.", "_all") time.sleep(5) sys.exit() self.dataThreads.append( threading.Thread(target=self.dataListenerThread, args=(mainTaskQueue, ethernetMTU), daemon=True)) self.dataThreads.append( threading.Thread(target=self.dataWriterThread, args=(self.writeDataQueue, ), daemon=True)) self.dataThreads[0].start() alert('Data listener thread started as daemon.') self.dataThreads[1].start() alert('Data injector thread started as daemon.')