| Mark Slee | 89e2bb8 | 2007-03-01 00:20:36 +0000 | [diff] [blame] | 1 | #!/usr/bin/env python | 
 | 2 | # | 
 | 3 | # Copyright (c) 2006- Facebook | 
 | 4 | # Distributed under the Thrift Software License | 
 | 5 | # | 
 | 6 | # See accompanying file LICENSE or visit the Thrift site at: | 
 | 7 | # http://developers.facebook.com/thrift/ | 
 | 8 |  | 
| Mark Slee | cde2b61 | 2006-09-03 21:13:07 +0000 | [diff] [blame] | 9 | from TTransport import * | 
 | 10 | import socket | 
 | 11 |  | 
 | 12 | class TSocket(TTransportBase): | 
 | 13 |  | 
 | 14 |   """Socket implementation of TTransport base.""" | 
 | 15 |  | 
| David Reiss | c16a8f6 | 2007-12-14 23:46:47 +0000 | [diff] [blame] | 16 |   def __init__(self, host='localhost', port=9090, unix_socket=None): | 
 | 17 |     """Initialize a TSocket | 
 | 18 |  | 
 | 19 |     @param host(str)  The host to connect to. | 
 | 20 |     @param port(int)  The (TCP) port to connect to. | 
 | 21 |     @param unix_socket(str)  The filename of a unix socket to connect to. | 
 | 22 |                              (host and port will be ignored.) | 
 | 23 |     """ | 
 | 24 |  | 
| Mark Slee | cde2b61 | 2006-09-03 21:13:07 +0000 | [diff] [blame] | 25 |     self.host = host | 
| Aditya Agarwal | 9bae5e7 | 2007-02-07 02:36:56 +0000 | [diff] [blame] | 26 |     self.port = port | 
| Mark Slee | cde2b61 | 2006-09-03 21:13:07 +0000 | [diff] [blame] | 27 |     self.handle = None | 
| David Reiss | c16a8f6 | 2007-12-14 23:46:47 +0000 | [diff] [blame] | 28 |     self._unix_socket = unix_socket | 
 | 29 |     self._timeout = None | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 30 |  | 
| Mark Slee | 4f0fed6 | 2006-10-02 17:50:08 +0000 | [diff] [blame] | 31 |   def setHandle(self, h): | 
| Mark Slee | c967656 | 2006-09-05 17:34:52 +0000 | [diff] [blame] | 32 |     self.handle = h | 
 | 33 |  | 
| Mark Slee | cde2b61 | 2006-09-03 21:13:07 +0000 | [diff] [blame] | 34 |   def isOpen(self): | 
| Aditya Agarwal | f954f97 | 2007-02-06 01:26:12 +0000 | [diff] [blame] | 35 |     return self.handle != None | 
 | 36 |  | 
 | 37 |   def setTimeout(self, ms): | 
| David Reiss | c16a8f6 | 2007-12-14 23:46:47 +0000 | [diff] [blame] | 38 |     if ms is None: | 
 | 39 |       self._timeout = None | 
| James Wang | e168d5e | 2007-07-24 23:59:51 +0000 | [diff] [blame] | 40 |     else: | 
| David Reiss | c16a8f6 | 2007-12-14 23:46:47 +0000 | [diff] [blame] | 41 |       self._timeout = ms/1000.0 | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 42 |  | 
| David Reiss | c16a8f6 | 2007-12-14 23:46:47 +0000 | [diff] [blame] | 43 |     if (self.handle != None): | 
 | 44 |       self.handle.settimeout(self._timeout) | 
| Mark Slee | cde2b61 | 2006-09-03 21:13:07 +0000 | [diff] [blame] | 45 |  | 
| David Reiss | c16a8f6 | 2007-12-14 23:46:47 +0000 | [diff] [blame] | 46 |   def _resolveAddr(self): | 
 | 47 |     if self._unix_socket is not None: | 
 | 48 |       return [(socket.AF_UNIX, socket.SOCK_STREAM, None, None, self._unix_socket)] | 
 | 49 |     else: | 
 | 50 |       return socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE | socket.AI_ADDRCONFIG) | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 51 |  | 
| Mark Slee | cde2b61 | 2006-09-03 21:13:07 +0000 | [diff] [blame] | 52 |   def open(self): | 
| Mark Slee | 92195ae | 2007-02-21 05:16:30 +0000 | [diff] [blame] | 53 |     try: | 
| David Reiss | c16a8f6 | 2007-12-14 23:46:47 +0000 | [diff] [blame] | 54 |       res0 = self._resolveAddr() | 
| Mark Slee | 2297460 | 2007-07-06 22:20:19 +0000 | [diff] [blame] | 55 |       for res in res0: | 
 | 56 |         self.handle = socket.socket(res[0], res[1]) | 
| David Reiss | c16a8f6 | 2007-12-14 23:46:47 +0000 | [diff] [blame] | 57 |         self.handle.settimeout(self._timeout) | 
| Mark Slee | 2297460 | 2007-07-06 22:20:19 +0000 | [diff] [blame] | 58 |         try: | 
 | 59 |           self.handle.connect(res[4]) | 
 | 60 |         except socket.error, e: | 
 | 61 |           if res is not res0[-1]: | 
 | 62 |             continue | 
 | 63 |           else: | 
 | 64 |             raise e | 
 | 65 |         break | 
| Mark Slee | 92195ae | 2007-02-21 05:16:30 +0000 | [diff] [blame] | 66 |     except socket.error, e: | 
| Mark Slee | 7679196 | 2007-03-14 02:47:35 +0000 | [diff] [blame] | 67 |       raise TTransportException(TTransportException.NOT_OPEN, 'Could not connect to %s:%d' % (self.host, self.port)) | 
| Mark Slee | cde2b61 | 2006-09-03 21:13:07 +0000 | [diff] [blame] | 68 |  | 
 | 69 |   def close(self): | 
| Mark Slee | d788b2e | 2006-09-07 01:26:35 +0000 | [diff] [blame] | 70 |     if self.handle != None: | 
 | 71 |       self.handle.close() | 
 | 72 |       self.handle = None | 
| Mark Slee | cde2b61 | 2006-09-03 21:13:07 +0000 | [diff] [blame] | 73 |  | 
| Mark Slee | cde2b61 | 2006-09-03 21:13:07 +0000 | [diff] [blame] | 74 |   def read(self, sz): | 
 | 75 |     buff = self.handle.recv(sz) | 
| Mark Slee | c967656 | 2006-09-05 17:34:52 +0000 | [diff] [blame] | 76 |     if len(buff) == 0: | 
| Mark Slee | 4f0fed6 | 2006-10-02 17:50:08 +0000 | [diff] [blame] | 77 |       raise TTransportException('TSocket read 0 bytes') | 
| Mark Slee | cde2b61 | 2006-09-03 21:13:07 +0000 | [diff] [blame] | 78 |     return buff | 
 | 79 |  | 
 | 80 |   def write(self, buff): | 
| Mark Slee | c967656 | 2006-09-05 17:34:52 +0000 | [diff] [blame] | 81 |     sent = 0 | 
 | 82 |     have = len(buff) | 
 | 83 |     while sent < have: | 
 | 84 |       plus = self.handle.send(buff) | 
 | 85 |       if plus == 0: | 
| Mark Slee | 92195ae | 2007-02-21 05:16:30 +0000 | [diff] [blame] | 86 |         raise TTransportException('TSocket sent 0 bytes') | 
| Mark Slee | c967656 | 2006-09-05 17:34:52 +0000 | [diff] [blame] | 87 |       sent += plus | 
 | 88 |       buff = buff[plus:] | 
| Mark Slee | cde2b61 | 2006-09-03 21:13:07 +0000 | [diff] [blame] | 89 |  | 
 | 90 |   def flush(self): | 
 | 91 |     pass | 
| Mark Slee | c967656 | 2006-09-05 17:34:52 +0000 | [diff] [blame] | 92 |  | 
 | 93 | class TServerSocket(TServerTransportBase): | 
 | 94 |  | 
 | 95 |   """Socket implementation of TServerTransport base.""" | 
 | 96 |  | 
 | 97 |   def __init__(self, port): | 
 | 98 |     self.port = port | 
 | 99 |     self.handle = None | 
| Mark Slee | 256bdc4 | 2007-11-27 08:42:19 +0000 | [diff] [blame] | 100 |  | 
| Mark Slee | c967656 | 2006-09-05 17:34:52 +0000 | [diff] [blame] | 101 |   def listen(self): | 
| Mark Slee | 256bdc4 | 2007-11-27 08:42:19 +0000 | [diff] [blame] | 102 |     res0 = socket.getaddrinfo(None, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE | socket.AI_ADDRCONFIG) | 
| Mark Slee | 2297460 | 2007-07-06 22:20:19 +0000 | [diff] [blame] | 103 |     for res in res0: | 
 | 104 |       if res[0] is socket.AF_INET6 or res is res0[-1]: | 
 | 105 |         break | 
 | 106 |  | 
 | 107 |     self.handle = socket.socket(res[0], res[1]) | 
| Mark Slee | 4f0fed6 | 2006-10-02 17:50:08 +0000 | [diff] [blame] | 108 |     self.handle.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | 
 | 109 |     if hasattr(self.handle, 'set_timeout'): | 
 | 110 |       self.handle.set_timeout(None) | 
| Mark Slee | 2297460 | 2007-07-06 22:20:19 +0000 | [diff] [blame] | 111 |     self.handle.bind(res[4]) | 
| Mark Slee | c967656 | 2006-09-05 17:34:52 +0000 | [diff] [blame] | 112 |     self.handle.listen(128) | 
 | 113 |  | 
 | 114 |   def accept(self): | 
 | 115 |     (client, addr) = self.handle.accept() | 
 | 116 |     result = TSocket() | 
| Mark Slee | 4f0fed6 | 2006-10-02 17:50:08 +0000 | [diff] [blame] | 117 |     result.setHandle(client) | 
| Mark Slee | c967656 | 2006-09-05 17:34:52 +0000 | [diff] [blame] | 118 |     return result | 
 | 119 |  | 
 | 120 |   def close(self): | 
 | 121 |     self.handle.close() | 
 | 122 |     self.handle = None |