Android grpc client is receiving GOAWAY from server with "too many pings" error. Now I realise that this is probably a server side issue, but I think the issue is that the client channel settings do not match that of the servers.
I have a C# gRPC server with the following settings:
List<ChannelOption> channelOptions = new List<ChannelOption>();
channelOptions.Add(new
ChannelOption("GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS",
1000));
channelOptions.Add(new
ChannelOption("GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA", 0));
channelOptions.Add(new
ChannelOption("GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS", 1));
this.server = new Server(channelOptions) {
Services = { TerminalService.BindService(this) },
Ports = {new ServerPort("0.0.0.0", 5000,
ServerCredentials.Insecure)}
};
On Android I have the following channel setup:
private val channel = ManagedChannelBuilder.forAddress(name, port)
.usePlaintext()
.keepAliveTime(10, TimeUnit.SECONDS)
.keepAliveWithoutCalls(true)
.build()
After a few min (however seems to be a random time). I get the goaway error. I noticed that if I stream data on the call then the error never happens. It is only when there is no data on the stream. This leads me to believe the issue is that the GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA needs to be set on the Android client aswell. Problem is for the life of me I cannot find where to set these channel settings on gRPC java. Can someone point out to me where I can set these channel settings? There are no examples where these have been set.
The channel options being specified are using the wrong names. Names like GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA are the C-defines for things like "grpc.http2.max_pings_without_data".
You can map from the C name to the key string by looking at grpc_types.h. You should prefer using one of the C# constants in ChannelOptions when it is available, but that doesn't seem to be an option in this case.
These options are not visible in the Java ManagedChannelBuilder API because they are server-specific settings. So instead they are visible on the ServerBuilder. See A8 client-side keepalive for reference to the Java keepalive API.
I wrote a netfilter hook function for incoming packets in linux kernel. Is there a way to get the receiving socket information from the hook function. The code is
register() {
hk.hook = hookfunction;
hk.hooknum = NF_INET_PRE_ROUTING;
hk.pf = PF_INET;
hk.priority = NF_IP_PRI_LAST;
}
static unsigned int hookfunction (void *priv,struct sk_buff,const struct nf_hook_state *state) {
if (skb->sk) {
printk("%d", skb->sk->sk_mark);
}
}
Lets assume I have a udp socket open at port 15000 and a udp packet arrives at port 15000. In the above written hook function how can I access the struct sock of the udp socket opened at port 15000. With the above code, the control doesnot pass the if(skb->sk) condition as if skb->sk is null. Can you please suggest me a way to get the struct sock of the socket or should I have to put the hook in some other position like NF_INET_LOCAL_IN,. I am also confused about the difference between NF_INET_XX_XX and NF_IP_XX_XX.
The kernel uses __inet_lookup_skb() internally to get sk from skb, which calls skb_steal_sock() first to check if skb->sk is NULL, if that is the case, it then calls __inet_lookup() to lookup sk.
However you might need to tweak the kernel a little bit because __inet_lookup_skb symbol is not exported and can't be called directly.
Some references from kernel source:
1 2 3
Regarding NF_INET_XX if you are talking about NF_IP_PRE_ROUTING and NF_INET_PRE_ROUTING I believe NF_IP_PRE_ROUTING is obsolete in recent kernel, as far as I know 4.4 has replaced it with NF_INET_PRE_ROUTING.
Hope that helps.
I can able to fetch all device ip addresses in Local Area Network with inetaddress class. What I need to do is reverse lookup ip-address and find as device name in network like : "Jimmie's Macbook"
My Code block which able to fetch all IP address over Local Network Range:
private ArrayList<String> scanSubNet(String subnet) {
ArrayList<String> hosts = new ArrayList<>();
InetAddress inetAddress;
for (int i = 1; i <= 255; i++) {
try {
inetAddress = InetAddress.getByName(subnet + String.valueOf(i));
if (inetAddress.isReachable(1000)) {
hosts.add(inetAddress.getHostName());
Log.d(TAG, InetAddress.getByAddress(inetAddress.getAddress()).getHostAddress());
Log.d(TAG, InetAddress.getByAddress(inetAddress.getAddress()).getCanonicalHostName());
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
return hosts;
}
And i am calling my method as;
ArrayList<String> subnetList = scanSubNet("192.168.1.");ArrayList<String> subnetList = scanSubNet("192.168.1.");
in Log.d(TAG, i am trying to get device name with reverse dns. But both of line gives me output as ip-address ( Not Device-Name as string)
Is there any chance to succeed it ?
Regards,
Onder.
I just do it with fetching MACID and match first 3digits which belongs manufacturers.
https://macvendors.com/ this website also provide api (Post/GET) to resolve MAC Address.
Instead of resolve fullname of MAC, you need to do Handshake peer to peer.
This is probably happening due to router misconfiguration.
Within a LAN, there are no crucial functions that depend on successful reverse DNS lookups, so a misconfiguration of that kind can easily go undetected for a long time.
It is kind of hard to tell what is wrong in your particular case without a lot more information about your LAN, but the first thing that comes to mind is configuring a proper "DNS Suffix" on the router. This is usually found under DHCP settings.
I've set up an ejabberd server that I want to use as a game server only.
What things do I have to pay attention to regarding security and which steps are needed so that I can start using it as a game server? Of course, I want to enable communication between local users only, no communication to JIDs from other servers may be possible.
How can I disable features such as IRC and server-to-server? This has to be done in the ejabberd.cfg, right? Do I have to comment these paragraphs out or fill in empty brackets for their options?
I've defined the following access control list:
[{acl, admin, {user, "admin", "localhost"}},
{acl, admin, {user, "admin", "***.***.***.***"}},
{acl, local, {server, "localhost"}},
{acl, local, {server, "***.***.***.***"}}].
Regarding the access rights, is the following definition okay or should I disable all communication channels except for PubSub?
[{access, c2s, [{deny, blocked}, {allow, all}]},
{access, pubsub_createnode, [{allow, all}]},
{access, s2s_shaper, [{fast, all}]},
{access, c2s_shaper, [{none, admin}, {normal, all}]},
{access, muc, [{allow, all}]},
{access, max_user_sessions, [{2, all}]},
{access, configure, [{allow, admin}]},
{access, muc_admin, [{allow, admin}]},
{access, max_user_offline_messages,
[{5000, admin}, {100, all}]},
{access, announce, [{allow, admin}]},
{access, register, [{deny, all}]},
{access, local, [{allow, local}]}].
Afterwards, can I access the server via client libraries such as smack / asmack or do I need BOSH, HTTP-polling etc? Are XMPP ports open on mobile devices, usually?
Those security considerations above are most important to me, as I don't want to run a game server with potential security risks. But apart from that, I can't really get PubSub running yet.
On the client side, in the Android application, I use the asmack library and the following code to initiate a new XMPP session and send a message:
private void startXMPP() {
new Thread(new Runnable() {
public void run() {
try {
org.jivesoftware.smackx.ConfigureProviderManager.configureProviderManager();
ConnectionConfiguration xmppConfig = new ConnectionConfiguration("123.123.123.123");
xmppConfig.setDebuggerEnabled(true);
if (Build.VERSION.SDK_INT >= 14) {
xmppConfig.setTruststoreType("AndroidCAStore");
xmppConfig.setTruststorePassword(null);
xmppConfig.setTruststorePath(null);
xmppConfig.setSendPresence(true);
xmppConfig.setSecurityMode(SecurityMode.disabled);
}
else {
xmppConfig.setTruststoreType("BKS");
String path = System.getProperty("javax.net.ssl.trustStore");
if (path == null) {
path = "/system/etc/security/cacerts.bks";
}
xmppConfig.setTruststorePath(path);
}
SASLAuthentication.supportSASLMechanism("PLAIN", 0);
XMPPConnection xmpp = new XMPPConnection(xmppConfig);
xmpp.connect();
xmpp.login("john", "password");
PubSubManager xmppPubsub = new PubSubManager(xmpp);
ConfigureForm form = new ConfigureForm(FormType.submit);
form.setPersistentItems(false);
form.setDeliverPayloads(true);
form.setAccessModel(AccessModel.open);
form.setPublishModel(PublishModel.open);
form.setSubscribe(true);
LeafNode xmppNode;
try {
xmppNode = (LeafNode) xmppPubsub.createNode("TESTNODE", form);
}
catch (XMPPException e) {
xmppNode = (LeafNode) xmppPubsub.getNode("TESTNODE");
}
SimplePayload payload = new SimplePayload("book", "pubsub:test:book", "");
xmppNode.addItemEventListener(new ItemEventCoordinator<Item>());
xmppNode.subscribe("john#123.123.123.123");
xmppNode.publish(new PayloadItem<SimplePayload>(payload));
}
catch (Exception e) {
System.out.println("XMPP Connection failed!");
e.printStackTrace();
}
}
}).start();
}
Unfortunately, this does not work. Do you see why? As I have debugging enabled, I can see the following error message in LogCat:
<iq from='pubsub.123.123.123.123' to='john#123.123.123.123/Smack' id='Jf****6' type='result'><pubsub xmlns='http://jabber.org/protocol/pubsub'><subscription jid='john#123.123.123.123' subscription='subscribed' subid='53******B2'/></pubsub></iq>
<iq id="Je4Mf-7" to="pubsub.123.123.123.123" type="set"><pubsub xmlns="http://jabber.org/protocol/pubsub"><publish node='TESTNODE'><item></item></publish></pubsub></iq>
<iq from='pubsub.123.123.123.123' to='john#123.123.123.123/Smack' type='error' id='Jf****7'><pubsub xmlns='http://jabber.org/protocol/pubsub'><publish node='TESTNODE'><item/></publish></pubsub><error code='400' type='modify'><bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/><payload-required xmlns='http://jabber.org/protocol/pubsub#errors'/></error></iq>
Edit:
I've not set the PubSub node name to home/server/username/whatever as described in the documentation. But at least the creation of the node is working, though, isn't it? I don't want a name in that format because I need names such as "game234234" so that all participating users can join that PubSub node.
Moreover, there seem to be attempts to contact pubsub.***.***.***.*** which is not there, as I have not created the subdomain pubsub. Is that the cause of the problem? Is PubSub only available via that subdomain? I don't know what to set up for that subdomain and would prefer to use PubSub just on the IP without subdomain.
You are getting an error on your publish() command since you have not specified the actual payload. Ideally, an exception should have been thrown since you created an invalid payload, but that seems to be the source of the error you are getting from the server.
Change
SimplePayload payload = new SimplePayload("book", "pubsub:test:book", "");
to:
SimplePayload payload = new SimplePayload("book", "pubsub:test:book", "<book xmlns='pubsub:test:book'>Romeo and Juliet</book>");
and it should successfully publish.
Now there are a couple of other problems you need to address.
You are creating your connection within the run method which ends after the publish(), thus your connection passes out of scope and is eligible for GC.
Try doing a getNode() before creating. In your current order, after the first time your code is run you will always be hitting the exception case. You should simply do a getNode() first and then create one if an exception is thrown, or you could avoid the exception altogether by doing a discoverNodes() first to determine if the node exists.
As for your point about the pubsub subdomain. This is the commonly used subdomain for pubsub in many (maybe all) XMPP servers, including ejabberd. You don't have to create it as the pubsub module already does that. It does exist already since you are already getting replies from it.
I am trying to connect my laptop(as client) to my android phone(as listener) using python-bluez on the laptop and android-bluetooth API on the phone.
I use the following code for my phone:
BluetoothServerSocket tmp = badapter.listenUsingRfcommWithServiceRecord(
badapter.getName(), MY_UUID);
BluetoothServerSocket bserversocket = tmp;
if(bserversocket != null)
{
BluetoothSocket acceptsocket = bserversocket.accept(timeout);
}
//timeout is set to about 15 sec
if(acceptsocket != null)
{
out.append("got the connection...\n");
}
and the following in python for my laptop client:
from bluetooth import *
btooth_addr = "38:EC:E4:57:1F:1B"
sock = BluetoothSocket(RFCOMM)
sock.connect((btooth_addr, 2))
print "Connected"
sock.close()
the listener time-outs without acknowledging any connections from the laptop, while the sender moves on to print 'Connected' on all attempts on different ports.
the problem is that I don't know and can't set the port/channel the android phone is listening on, and also that I am required to fill in a port number as second argument of 'connect'(2 in this snippet).
please help me out - my sole goal at this time is to get the connection attempt acknowledged by the phone.
Have a look at the pybluez documentation(source code) for establishing client connections.
You can get the correct port for the supplied Bluetooth address and UUID using find_service.
Then connect your socket just as you do in your code, replacing hardcoded port value with the correct one.
Don't forget to vote up!