use of com.biglybt.core.proxy.AEProxyFactory.PluginProxy in project BiglyBT by BiglySoftware.
the class TCPTransportImpl method connectOutbound.
/**
* Request the transport connection be established.
* NOTE: Will automatically connect via configured proxy if necessary.
* @param address remote peer address to connect to
* @param listener establishment failure/success listener
*/
@Override
public void connectOutbound(final ByteBuffer initial_data, final ConnectListener listener, final int priority) {
if (!TCPNetworkManager.TCP_OUTGOING_ENABLED) {
listener.connectFailure(new Throwable("Outbound TCP connections disabled"));
return;
}
if (has_been_closed) {
listener.connectFailure(new Throwable("Connection already closed"));
return;
}
if (getFilter() != null) {
// already connected
Debug.out("socket_channel != null");
listener.connectSuccess(this, initial_data);
return;
}
final InetSocketAddress address = protocol_endpoint.getAddress();
if (!address.equals(ProxyLoginHandler.DEFAULT_SOCKS_SERVER_ADDRESS)) {
if (address.isUnresolved()) {
String host = address.getHostName();
if (AENetworkClassifier.categoriseAddress(host) != AENetworkClassifier.AT_PUBLIC) {
Map<String, Object> opts = new HashMap<>();
Object peer_nets = listener.getConnectionProperty(AEProxyFactory.PO_PEER_NETWORKS);
if (peer_nets != null) {
opts.put(AEProxyFactory.PO_PEER_NETWORKS, peer_nets);
}
PluginProxy pp = plugin_proxy;
plugin_proxy = null;
if (pp != null) {
// most likely crypto fallback connection so don't assume it is a bad
// outcome
pp.setOK(true);
}
plugin_proxy = AEProxyFactory.getPluginProxy("outbound connection", host, address.getPort(), opts);
}
}
if (plugin_proxy == null) {
is_socks = COConfigurationManager.getBooleanParameter("Proxy.Data.Enable");
}
}
final TCPTransportImpl transport_instance = this;
TCPConnectionManager.ConnectListener connect_listener = new TCPConnectionManager.ConnectListener() {
@Override
public int connectAttemptStarted(int default_connect_timeout) {
return (listener.connectAttemptStarted(default_connect_timeout));
}
@Override
public void connectSuccess(final SocketChannel channel) {
if (channel == null) {
String msg = "connectSuccess:: given channel == null";
Debug.out(msg);
setConnectResult(false);
listener.connectFailure(new Exception(msg));
return;
}
if (has_been_closed) {
// closed between select ops
// just close it
TCPNetworkManager.getSingleton().getConnectDisconnectManager().closeConnection(channel);
setConnectResult(false);
listener.connectFailure(new Throwable("Connection has been closed"));
return;
}
connect_request_key = null;
description = (is_inbound_connection ? "R" : "L") + ": " + channel.socket().getInetAddress().getHostAddress() + ": " + channel.socket().getPort();
PluginProxy pp = plugin_proxy;
if (is_socks) {
// proxy server connection established, login
if (Logger.isEnabled())
Logger.log(new LogEvent(LOGID, "Socket connection established to proxy server [" + description + "], login initiated..."));
// set up a transparent filter for socks negotiation
setFilter(TCPTransportHelperFilterFactory.createTransparentFilter(channel));
new ProxyLoginHandler(transport_instance, address, new ProxyLoginHandler.ProxyListener() {
@Override
public void connectSuccess() {
if (Logger.isEnabled())
Logger.log(new LogEvent(LOGID, "Proxy [" + description + "] login successful."));
handleCrypto(address, channel, initial_data, priority, listener);
}
@Override
public void connectFailure(Throwable failure_msg) {
close("Proxy login failed");
listener.connectFailure(failure_msg);
}
});
} else if (pp != null) {
if (Logger.isEnabled()) {
Logger.log(new LogEvent(LOGID, "Socket connection established via plugin proxy [" + description + "], login initiated..."));
}
// set up a transparent filter for socks negotiation
setFilter(TCPTransportHelperFilterFactory.createTransparentFilter(channel));
String pp_host = pp.getHost();
InetSocketAddress ia_address;
if (AENetworkClassifier.categoriseAddress(pp_host) == AENetworkClassifier.AT_PUBLIC) {
ia_address = new InetSocketAddress(pp.getHost(), pp.getPort());
} else {
ia_address = InetSocketAddress.createUnresolved(pp_host, pp.getPort());
}
new ProxyLoginHandler(transport_instance, ia_address, new ProxyLoginHandler.ProxyListener() {
@Override
public void connectSuccess() {
if (Logger.isEnabled()) {
Logger.log(new LogEvent(LOGID, "Proxy [" + description + "] login successful."));
}
setConnectResult(true);
handleCrypto(address, channel, initial_data, priority, listener);
}
@Override
public void connectFailure(Throwable failure_msg) {
setConnectResult(false);
close("Proxy login failed");
listener.connectFailure(failure_msg);
}
}, "V4a", "", "");
} else {
// direct connection established, notify
handleCrypto(address, channel, initial_data, priority, listener);
}
}
@Override
public void connectFailure(Throwable failure_msg) {
connect_request_key = null;
setConnectResult(false);
listener.connectFailure(failure_msg);
}
};
connect_request_key = connect_listener;
InetSocketAddress to_connect;
PluginProxy pp = plugin_proxy;
if (is_socks) {
to_connect = ProxyLoginHandler.getProxyAddress(address);
} else if (pp != null) {
to_connect = (InetSocketAddress) pp.getProxy().address();
} else {
to_connect = address;
}
TCPNetworkManager.getSingleton().getConnectDisconnectManager().requestNewConnection(to_connect, connect_listener, priority);
}
use of com.biglybt.core.proxy.AEProxyFactory.PluginProxy in project BiglyBT by BiglySoftware.
the class VersionCheckClient method executeHTTP.
private Map executeHTTP(Map data_to_send, boolean v6) throws Exception {
if (v6 && !enable_v6) {
throw (new Exception("IPv6 is disabled"));
}
String host = getHost(v6, HTTP_SERVER_ADDRESS_V6, HTTP_SERVER_ADDRESS_V4);
if (Logger.isEnabled())
Logger.log(new LogEvent(LOGID, "VersionCheckClient retrieving " + "version information from " + host + ":" + HTTP_SERVER_PORT + " via HTTP"));
String url_str = "http://" + (v6 ? UrlUtils.convertIPV6Host(host) : host) + (HTTP_SERVER_PORT == 80 ? "" : (":" + HTTP_SERVER_PORT)) + "/version?";
url_str += URLEncoder.encode(new String(BEncoder.encode(data_to_send), "ISO-8859-1"), "ISO-8859-1");
URL url = new URL(url_str);
try {
if (COConfigurationManager.getBooleanParameter("update.anonymous")) {
throw (new Exception("Direct HTTP disabled for anonymous updates"));
}
Properties http_properties = new Properties();
http_properties.put(ClientIDGenerator.PR_URL, url);
try {
ClientIDManagerImpl cman = ClientIDManagerImpl.getSingleton();
if (cman != null && cman.getGenerator() != null) {
cman.generateHTTPProperties(null, http_properties);
}
} catch (Throwable e) {
Debug.out(e);
throw (new IOException(e.getMessage()));
}
url = (URL) http_properties.get(ClientIDGenerator.PR_URL);
HttpURLConnection url_connection = (HttpURLConnection) url.openConnection();
url_connection.setConnectTimeout(10 * 1000);
url_connection.setReadTimeout(10 * 1000);
url_connection.connect();
try {
InputStream is = url_connection.getInputStream();
Map reply = BDecoder.decode(new BufferedInputStream(is));
preProcessReply(reply, v6);
return (reply);
} finally {
url_connection.disconnect();
}
} catch (Exception e) {
if (!v6) {
PluginProxy proxy = AEProxyFactory.getPluginProxy("Vuze version check", url);
if (proxy != null) {
boolean worked = false;
try {
HttpURLConnection url_connection = (HttpURLConnection) proxy.getURL().openConnection(proxy.getProxy());
url_connection.setConnectTimeout(30 * 1000);
url_connection.setReadTimeout(30 * 1000);
url_connection.connect();
try {
InputStream is = url_connection.getInputStream();
Map reply = BDecoder.decode(new BufferedInputStream(is));
preProcessReply(reply, v6);
worked = true;
return (reply);
} finally {
url_connection.disconnect();
}
} finally {
proxy.setOK(worked);
}
}
}
throw (e);
}
}
use of com.biglybt.core.proxy.AEProxyFactory.PluginProxy in project BiglyBT by BiglySoftware.
the class SFPluginDetailsLoaderImpl method loadPluginList.
protected void loadPluginList() throws SFPluginDetailsException {
try {
String page_url_to_use = addEPIDS(page_url);
URL original_url = new URL(page_url_to_use);
URL url = original_url;
Proxy proxy = null;
PluginProxy plugin_proxy = null;
boolean tried_proxy = false;
boolean ok = false;
if (COConfigurationManager.getBooleanParameter("update.anonymous")) {
tried_proxy = true;
plugin_proxy = AEProxyFactory.getPluginProxy("loading plugin details", url);
if (plugin_proxy == null) {
throw (new SFPluginDetailsException("Proxy not available"));
} else {
url = plugin_proxy.getURL();
proxy = plugin_proxy.getProxy();
}
}
try {
while (true) {
try {
ResourceDownloader dl = rd_factory.create(url, proxy);
if (plugin_proxy != null) {
dl.setProperty("URL_HOST", plugin_proxy.getURLHostRewrite());
}
dl = rd_factory.getRetryDownloader(dl, 5);
dl.addListener(this);
Properties details = new Properties();
InputStream is = dl.download();
details.load(is);
is.close();
Iterator it = details.keySet().iterator();
while (it.hasNext()) {
String plugin_id = (String) it.next();
String data = (String) details.get(plugin_id);
int pos = 0;
List bits = new ArrayList();
while (pos < data.length()) {
int p1 = data.indexOf(';', pos);
if (p1 == -1) {
bits.add(data.substring(pos).trim());
break;
} else {
bits.add(data.substring(pos, p1).trim());
pos = p1 + 1;
}
}
if (bits.size() < 3) {
Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "SF loadPluginList failed for plugin '" + plugin_id + "'. Details array is " + bits.size() + " (3 min)"));
} else {
String version = (String) bits.get(0);
String cvs_version = (String) bits.get(1);
String name = (String) bits.get(2);
String category = "";
if (bits.size() > 3) {
category = (String) bits.get(3);
}
plugin_ids.add(plugin_id);
plugin_map.put(plugin_id.toLowerCase(MessageText.LOCALE_ENGLISH), new SFPluginDetailsImpl(this, plugin_id, version, cvs_version, name, category));
}
}
ok = true;
break;
} catch (Throwable e) {
if (!tried_proxy) {
tried_proxy = true;
plugin_proxy = AEProxyFactory.getPluginProxy("loading plugin details", url);
if (plugin_proxy == null) {
throw (e);
} else {
url = plugin_proxy.getURL();
proxy = plugin_proxy.getProxy();
}
} else {
throw (e);
}
}
}
} finally {
if (plugin_proxy != null) {
plugin_proxy.setOK(ok);
}
}
plugin_ids_loaded = true;
plugin_ids_loaded_at = SystemTime.getCurrentTime();
} catch (Throwable e) {
Debug.printStackTrace(e);
throw (new SFPluginDetailsException("Plugin list load failed", e));
}
}
use of com.biglybt.core.proxy.AEProxyFactory.PluginProxy in project BiglyBT by BiglySoftware.
the class ResourceDownloaderURLImpl method trimForDisplay.
protected String trimForDisplay(URL url) {
if (force_proxy != null) {
PluginProxy pp = AEProxyFactory.getPluginProxy(force_proxy);
if (pp != null) {
try {
url = new URL(pp.getTarget());
} catch (Throwable e) {
}
}
}
String str = url.toString();
int pos = str.indexOf('?');
if (pos != -1) {
str = str.substring(0, pos);
}
return (str);
}
use of com.biglybt.core.proxy.AEProxyFactory.PluginProxy in project BiglyBT by BiglySoftware.
the class NetStatusPluginTester method run.
public void run(Core core) {
final NetworkAdmin admin = NetworkAdmin.getSingleton();
boolean checked_public = false;
Set<InetAddress> public_addresses = new HashSet<>();
InetAddress def_pa = admin.getDefaultPublicAddress();
if (def_pa != null) {
log("Default public address is " + def_pa.getHostAddress());
addPublicAddress(public_addresses, def_pa);
checked_public = true;
}
InetAddress[] bindable = admin.getBindableAddresses();
String bindable_str = "";
for (InetAddress b : bindable) {
bindable_str += (bindable_str.length() == 0 ? "" : ", ") + b.getHostAddress();
}
log("Bindable addresses: " + bindable_str);
if (doTest(TEST_NAT_PROXIES)) {
checked_public = true;
NetworkAdminNATDevice[] nat_devices = admin.getNATDevices(core);
log(nat_devices.length + " NAT device" + (nat_devices.length == 1 ? "" : "s") + " found");
for (int i = 0; i < nat_devices.length; i++) {
NetworkAdminNATDevice device = nat_devices[i];
InetAddress ext_address = device.getExternalAddress();
addPublicAddress(public_addresses, ext_address);
log(" " + device.getString());
}
NetworkAdminSocksProxy[] socks_proxies = admin.getSocksProxies();
if (socks_proxies.length == 0) {
log("No SOCKS proxy found");
} else if (socks_proxies.length == 1) {
log("One SOCKS proxy found");
} else {
log(socks_proxies.length + " SOCKS proxies found");
}
for (int i = 0; i < socks_proxies.length; i++) {
NetworkAdminSocksProxy proxy = socks_proxies[i];
log(" " + proxy.getString());
}
NetworkAdminHTTPProxy http_proxy = admin.getHTTPProxy();
if (http_proxy == null) {
log("No HTTP proxy found");
} else {
log("HTTP proxy found");
log(" " + http_proxy.getString());
}
}
InetAddress[] bind_addresses = admin.getAllBindAddresses(false);
int num_binds = 0;
for (int i = 0; i < bind_addresses.length; i++) {
if (bind_addresses[i] != null) {
num_binds++;
}
}
if (num_binds == 0) {
log("No explicit bind address set");
} else {
log(num_binds + " bind addresses");
for (int i = 0; i < bind_addresses.length; i++) {
if (bind_addresses[i] != null) {
log(" " + bind_addresses[i].getHostAddress());
}
}
}
if (doTest(TEST_OUTBOUND)) {
checked_public = true;
NetworkAdminProtocol[] outbound_protocols = admin.getOutboundProtocols(core);
if (outbound_protocols.length == 0) {
log("No outbound protocols");
} else {
for (int i = 0; i < outbound_protocols.length; i++) {
if (test_cancelled) {
return;
}
NetworkAdminProtocol protocol = outbound_protocols[i];
log("Testing " + protocol.getName());
try {
InetAddress public_address = protocol.test(null, new NetworkAdminProgressListener() {
@Override
public void reportProgress(String task) {
log(" " + task);
}
});
logSuccess(" Test successful");
addPublicAddress(public_addresses, public_address);
} catch (Throwable e) {
logError(" Test failed", e);
}
}
}
}
if (doTest(TEST_INBOUND)) {
checked_public = true;
NetworkAdminProtocol[] inbound_protocols = admin.getInboundProtocols(core);
if (inbound_protocols.length == 0) {
log("No inbound protocols");
} else {
for (int i = 0; i < inbound_protocols.length; i++) {
if (test_cancelled) {
return;
}
NetworkAdminProtocol protocol = inbound_protocols[i];
log("Testing " + protocol.getName());
try {
InetAddress public_address = protocol.test(null, new NetworkAdminProgressListener() {
@Override
public void reportProgress(String task) {
log(" " + task);
}
});
logSuccess(" Test successful");
addPublicAddress(public_addresses, public_address);
} catch (Throwable e) {
logError(" Test failed", e);
logInfo(" Check your port forwarding for " + protocol.getTypeString() + " " + protocol.getPort());
}
}
}
}
if (checked_public) {
if (public_addresses.size() == 0) {
log("No public addresses found");
} else {
Iterator<InetAddress> it = public_addresses.iterator();
log(public_addresses.size() + " public/external addresses found");
while (it.hasNext()) {
InetAddress pub_address = it.next();
log(" " + pub_address.getHostAddress());
try {
NetworkAdminASN asn = admin.lookupASN(pub_address);
log(" AS details: " + asn.getString());
} catch (Throwable e) {
logError(" failed to lookup AS", e);
}
}
}
}
String[][] services = { // directly referenced at index 0 below
{ "BiglyBT Website", Constants.URL_CLIENT_HOME }, { "Version Server", "http://" + Constants.VERSION_SERVER_V4 + "/?dee" }, { "Plugins Website", Constants.PLUGINS_WEB_SITE } };
if (doTest(TEST_BIGLYBT_SERVICES)) {
log("BiglyBT Services test");
for (String[] service : services) {
if (test_cancelled) {
return;
}
try {
URL url = new URL(service[1]);
log(" " + service[0] + " - " + url.getHost());
boolean is_https = url.getProtocol().equals("https");
if (is_https) {
String[] host_bits = url.getHost().split("\\.");
String host_match = "." + host_bits[host_bits.length - 2] + "." + host_bits[host_bits.length - 1];
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String host, SSLSession session) {
return (true);
}
});
con.setInstanceFollowRedirects(false);
con.setConnectTimeout(30 * 1000);
con.setReadTimeout(30 * 1000);
con.getResponseCode();
con.getInputStream();
Certificate[] certs = con.getServerCertificates();
if (certs == null || certs.length == 0) {
logError(" No certificates returned");
} else {
Certificate cert = certs[0];
java.security.cert.X509Certificate x509_cert;
if (cert instanceof java.security.cert.X509Certificate) {
x509_cert = (java.security.cert.X509Certificate) cert;
} else {
java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory.getInstance("X.509");
x509_cert = (java.security.cert.X509Certificate) cf.generateCertificate(new ByteArrayInputStream(cert.getEncoded()));
}
log(" Certificate: " + x509_cert.getSubjectDN());
Collection<List<?>> alt_names = x509_cert.getSubjectAlternativeNames();
boolean match = false;
for (List<?> alt_name : alt_names) {
int type = ((Number) alt_name.get(0)).intValue();
if (type == 2) {
// DNS name
String dns_name = (String) alt_name.get(1);
if (dns_name.endsWith(host_match)) {
match = true;
break;
}
}
}
if (!match) {
logError(" Failed: Host '" + host_match + "' not found in certificate");
} else {
logSuccess(" Connection result: " + con.getResponseCode() + "/" + con.getResponseMessage());
}
}
} else {
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setInstanceFollowRedirects(false);
con.setConnectTimeout(30 * 1000);
con.setReadTimeout(30 * 1000);
if (con.getResponseCode() != 200) {
throw (new Exception("Connection failed: " + con.getResponseCode() + "/" + con.getResponseMessage()));
}
Map resp = BDecoder.decode(new BufferedInputStream(con.getInputStream(), 16 * 1024));
if (resp != null && resp.containsKey("version")) {
logSuccess(" Connection result: " + con.getResponseCode() + "/" + con.getResponseMessage());
} else {
logError(" Unexpected reply from server: " + resp);
}
}
} catch (Throwable e) {
logError(" Failed: " + Debug.getNestedExceptionMessage(e));
}
}
}
if (doTest(TEST_PROXY_CONNECT)) {
log("Indirect Connect test");
try {
URL target = new URL(services[0][1]);
PluginProxy proxy = AEProxyFactory.getPluginProxy("Network Status test", target);
if (proxy == null) {
logError(" No plugin proxy available");
logInfo(" For the plugin installer refer to the 'Tor Helper' plugin");
} else {
log(" Connecting to " + target.toExternalForm());
HttpURLConnection con = (HttpURLConnection) proxy.getURL().openConnection(proxy.getProxy());
if (con instanceof HttpsURLConnection) {
((HttpsURLConnection) con).setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String host, SSLSession session) {
return (true);
}
});
}
con.setRequestProperty("HOST", proxy.getURLHostRewrite());
con.setInstanceFollowRedirects(false);
con.setConnectTimeout(60 * 1000);
con.setReadTimeout(30 * 1000);
try {
int resp = con.getResponseCode();
if (con instanceof HttpsURLConnection) {
Certificate[] certs = ((HttpsURLConnection) con).getServerCertificates();
if (certs == null || certs.length == 0) {
logError(" No certificates returned");
} else {
Certificate cert = certs[0];
java.security.cert.X509Certificate x509_cert;
if (cert instanceof java.security.cert.X509Certificate) {
x509_cert = (java.security.cert.X509Certificate) cert;
} else {
java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory.getInstance("X.509");
x509_cert = (java.security.cert.X509Certificate) cf.generateCertificate(new ByteArrayInputStream(cert.getEncoded()));
}
log(" Certificate: " + x509_cert.getSubjectDN());
}
}
if (resp == 200) {
logSuccess(" Connection result: " + con.getResponseCode() + "/" + con.getResponseMessage());
} else {
log(" Connection result: " + con.getResponseCode() + "/" + con.getResponseMessage());
}
} finally {
proxy.setOK(true);
}
}
} catch (Throwable e) {
logError(" Failed: " + Debug.getNestedExceptionMessage(e));
logError(" Check the logs for the 'Tor Helper Plugin' (Tools->Plugins->Log Views)");
}
}
if (doTest(TEST_BT_CONNECT)) {
log("Distributed protocol test");
NetStatusProtocolTesterBT bt_test = plugin.getProtocolTester().runTest(new NetStatusProtocolTesterListener() {
private List sessions = new ArrayList();
@Override
public void complete(NetStatusProtocolTesterBT tester) {
log("Results", false);
if (tester.getOutboundConnects() < 4) {
log(" insufficient outbound connects for analysis", false);
return;
}
int outgoing_seed_ok = 0;
int outgoing_leecher_ok = 0;
int outgoing_seed_bad = 0;
int outgoing_leecher_bad = 0;
int incoming_connect_ok = 0;
for (int i = 0; i < sessions.size(); i++) {
NetStatusProtocolTesterBT.Session session = (NetStatusProtocolTesterBT.Session) sessions.get(i);
if (session.isOK()) {
if (session.isInitiator()) {
if (session.isSeed()) {
outgoing_seed_ok++;
} else {
outgoing_leecher_ok++;
}
} else {
incoming_connect_ok++;
}
} else {
if (session.isConnected()) {
if (session.isInitiator()) {
if (session.isSeed()) {
outgoing_seed_bad++;
} else {
outgoing_leecher_bad++;
}
} else {
incoming_connect_ok++;
}
}
}
log(" " + (session.isInitiator() ? "Outbound" : "Inbound") + "," + (session.isSeed() ? "Seed" : "Leecher") + "," + session.getProtocolString(), false);
}
boolean good = true;
if (incoming_connect_ok == 0) {
logError(" No incoming connections received, likely NAT problems");
good = false;
}
if (outgoing_leecher_ok > 0 && outgoing_seed_ok == 0 && outgoing_seed_bad > 0) {
logError(" Outgoing seed connects appear to be failing while non-seeds succeed");
good = false;
}
if (good) {
logSuccess(" Test successful");
}
}
@Override
public void sessionAdded(NetStatusProtocolTesterBT.Session session) {
synchronized (sessions) {
sessions.add(session);
}
}
@Override
public void log(String str, boolean detailed) {
NetStatusPluginTester.this.log(" " + str, detailed);
}
@Override
public void logError(String str) {
NetStatusPluginTester.this.logError(" " + str);
}
@Override
public void logError(String str, Throwable e) {
NetStatusPluginTester.this.logError(" " + str, e);
}
});
while (!bt_test.waitForCompletion(5000)) {
if (isCancelled()) {
bt_test.destroy();
break;
}
log(" Status: " + bt_test.getStatus());
}
}
if (doTest(TEST_IPV6)) {
log("IPv6 test");
InetAddress ipv6_address = admin.getDefaultPublicAddressV6();
if (ipv6_address == null) {
log(" No default public IPv6 address found");
} else {
log(" Default public IPv6 address: " + ipv6_address.getHostAddress());
log(" Testing connectivity...");
String res = VersionCheckClient.getSingleton().getExternalIpAddress(false, true, true);
if (res != null && res.length() > 0) {
logSuccess(" Connect succeeded, reported IPv6 address: " + res);
} else {
logError(" Connect failed");
}
}
}
}
Aggregations