show popup if qr scanner not enabled
[electrum-nvc.git] / lib / interface.py
index cc1553a..0b1cba4 100644 (file)
@@ -49,7 +49,7 @@ def check_cert(host, cert):
 def cert_has_expired(cert_path):
     try:
         import OpenSSL
-    except:
+    except Exception:
         print_error("Warning: cannot import OpenSSL")
         return False
     from OpenSSL import crypto as c
@@ -105,15 +105,18 @@ class Interface(threading.Thread):
         #json
         self.message_id = 0
         self.unanswered_requests = {}
-        self.pending_transactions_for_notifications= []
 
         # parse server
         self.server = server
-        host, port, protocol = self.server.split(':')
-        port = int(port)
-            
+        try:
+            host, port, protocol = self.server.split(':')
+            port = int(port)
+        except Exception:
+            self.server = None
+            return
+
         if protocol not in 'ghst':
-            raise BaseException('Unknown protocol: %s'%protocol)
+            raise Exception('Unknown protocol: %s'%protocol)
 
         self.host = host
         self.port = port
@@ -192,7 +195,7 @@ class Interface(threading.Thread):
         self.connection_msg = ('https' if self.use_ssl else 'http') + '://%s:%d'%( self.host, self.port )
         try:
             self.poll()
-        except:
+        except Exception:
             print_error("http init session failed")
             self.is_connected = False
             return
@@ -214,7 +217,7 @@ class Interface(threading.Thread):
                 break
             except socket.error:
                 break
-            except:
+            except Exception:
                 traceback.print_exc(file=sys.stdout)
                 break
             
@@ -240,11 +243,13 @@ class Interface(threading.Thread):
         t1 = time.time()
 
         data = []
+        ids = []
         for m in messages:
             method, params = m
             if type(params) != type([]): params = [params]
             data.append( { 'method':method, 'id':self.message_id, 'params':params } )
             self.unanswered_requests[self.message_id] = method, params, callback
+            ids.append(self.message_id)
             self.message_id += 1
 
         if data:
@@ -261,7 +266,7 @@ class Interface(threading.Thread):
         try:
             req = urllib2.Request(self.connection_msg, data_json, headers)
             response_stream = urllib2.urlopen(req, timeout=DEFAULT_TIMEOUT)
-        except:
+        except Exception:
             return
 
         for index, cookie in enumerate(cj):
@@ -287,6 +292,7 @@ class Interface(threading.Thread):
 
         self.rtime = time.time() - t1
         self.is_connected = True
+        return ids
 
 
 
@@ -311,18 +317,31 @@ class Interface(threading.Thread):
                 is_new = True
                 # get server certificate.
                 # Do not use ssl.get_server_certificate because it does not work with proxy
-                s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
                 try:
-                    s.connect((self.host, self.port))
-                except:
-                    # print_error("failed to connect", self.host, self.port)
+                    l = socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM)
+                except socket.gaierror:
+                    print_error("error: cannot resolve", self.host)
                     return
 
-                try:
-                    s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv3, cert_reqs=ssl.CERT_NONE, ca_certs=None)
-                except ssl.SSLError, e:
-                    print_error("SSL error:", self.host, e)
+                for res in l:
+                    try:
+                        s = socket.socket( res[0], socket.SOCK_STREAM )
+                        s.connect(res[4])
+                    except:
+                        s = None
+                        continue
+
+                    try:
+                        s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv3, cert_reqs=ssl.CERT_NONE, ca_certs=None)
+                    except ssl.SSLError, e:
+                        print_error("SSL error retrieving SSL certificate:", self.host, e)
+                        s = None
+
+                    break
+
+                if s is None:
                     return
+
                 dercert = s.getpeercert(True)
                 s.close()
                 cert = ssl.DER_cert_to_PEM_cert(dercert)
@@ -335,14 +354,24 @@ class Interface(threading.Thread):
             else:
                 is_new = False
 
+        try:
+            addrinfo = socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM)
+        except socket.gaierror:
+            print_error("error: cannot resolve", self.host)
+            return
 
-        s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
-        s.settimeout(2)
-        s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
+        for res in addrinfo:
+            try:
+                s = socket.socket( res[0], socket.SOCK_STREAM )
+                s.settimeout(2)
+                s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
+                s.connect(res[4])
+            except:
+                s = None
+                continue
+            break
 
-        try:
-            s.connect(( self.host.encode('ascii'), int(self.port)))
-        except:
+        if s is None:
             print_error("failed to connect", self.host, self.port)
             return
 
@@ -358,15 +387,18 @@ class Interface(threading.Thread):
                 if e.errno != 1:
                     return
                 if is_new:
-                    os.rename(temporary_path, cert_path + '.rej')
+                    rej = cert_path + '.rej'
+                    if os.path.exists(rej):
+                        os.unlink(rej)
+                    os.rename(temporary_path, rej)
                 else:
                     if cert_has_expired(cert_path):
                         print_error("certificate has expired:", cert_path)
                         os.unlink(cert_path)
                     else:
-                        print_msg("wrong certificate", self.host)
+                        print_error("wrong certificate", self.host)
                 return
-            except:
+            except Exception:
                 print_error("wrap_socket failed", self.host)
                 traceback.print_exc(file=sys.stdout)
                 return
@@ -394,7 +426,9 @@ class Interface(threading.Thread):
                 except ssl.SSLError:
                     timeout = True
                 except socket.error, err:
-                    if err.errno in [11, 10035]:
+                    if err.errno == 60:
+                        timeout = True
+                    elif err.errno in [11, 10035]:
                         print_error("socket errno", err.errno)
                         time.sleep(0.1)
                         continue
@@ -420,7 +454,7 @@ class Interface(threading.Thread):
                     c = json.loads(c)
                     self.queue_json_response(c)
 
-        except:
+        except Exception:
             traceback.print_exc(file=sys.stdout)
 
         self.is_connected = False
@@ -532,6 +566,8 @@ class Interface(threading.Thread):
             self.s.shutdown(socket.SHUT_RDWR)
             self.s.close()
 
+        self.is_connected = False
+
 
     def is_up_to_date(self):
         return self.unanswered_requests == {}
@@ -539,6 +575,8 @@ class Interface(threading.Thread):
 
 
     def start(self, queue = None, wait = False):
+        if not self.server:
+            return
         self.queue = queue if queue else Queue.Queue()
         threading.Thread.start(self)
         if wait:
@@ -559,6 +597,22 @@ class Interface(threading.Thread):
         self.queue.put(self)
 
 
+    def synchronous_get(self, requests, timeout=100000000):
+        queue = Queue.Queue()
+        ids = self.send(requests, lambda i,r: queue.put(r))
+        id2 = ids[:]
+        res = {}
+        while ids:
+            r = queue.get(True, timeout)
+            _id = r.get('id')
+            if _id in ids:
+                ids.remove(_id)
+                res[_id] = r.get('result')
+        out = []
+        for _id in id2:
+            out.append(res[_id])
+        return out
+
 
 if __name__ == "__main__":