Bonjour to JmDNS from iOS: What's the name? - java

I'm sure I'm just a few letters away from getting this to work, but maybe not...
On the server-side, I've got this (Java);
ServiceInfo info = ServiceInfo.create("_mjdj._tcp.local.", "foo", 1268, 0, 0, "path=index.html");
jmdns.registerService(info);
This works perfectly with my Java client or a Bonjour Browser (service shows as "_mjdj._tcp." in local). So in Java this works:
jmdns.list("_mjdj._tcp.local.");
But from an iOS client I can't seem to find the service (or something). I've got the delegate methods in place, but this
NSNetServiceBrowser *browser = [[[NSNetServiceBrowser alloc] init] autorelease];
[browser setDelegate:self];
[browser searchForServicesOfType:#"_mjdj._tcp.local." inDomain:#""];
produces this error
{
NSNetServicesErrorCode = "-72004";
NSNetServicesErrorDomain = 10;
}
and if I do this (guessing)
[browser searchForServicesOfType:#"_mjdj._tcp." inDomain:#"local"];
the netServiceBrowserWillSearch gets called but nothing after that.

[browser searchForServicesOfType:#"_mjdj._tcp.local." inDomain:#""];
That's your error. You want
[browser searchForServicesOfType:#"_mjdj._tcp." inDomain:#""];
The "local." part is the domain, so you could use the domain "local." if you want, but #"" means use the default registration domains (which includes, but is not necessarily limited to, "local."). The reason you're confused is because the Java API is bad. It should not be squishing the service type and domain together like that.
Note that your attempt at using #"local" failed, most likely because you forgot the trailing period. I suggest you just use #"" though.

Related

Unknown Move Destination: STORESCP

I have just installed dcm4chee4-4.4.0.Beta1, following INSTALL.md instructions and everything works fine except movescu test.
When I run this test I can see an error in standalone/log/server.log (previously I launched in another console storescp -b11115). This is the error:
2015-09-13 12:48:49,105 INFO [org.dcm4che3.net.Association] (pool-6-thread-7) DCM4CHEE<-MOVESCU(7): processing 1:C-MOVE-RQ[pcid=1, prior=0
cuid=1.2.840.10008.5.1.4.1.2.2.2 - Study Root Query/Retrieve Information Model - MOVE
tsuid=1.2.840.10008.1.2 - Implicit VR Little Endian failed. Caused by: org.dcm4che3.net.service.DicomServiceException: Unknown Move Destination: STORESCP#localhost:11115
at org.dcm4chee.archive.retrieve.scp.CMoveSCP.calculateMatches(CMoveSCP.java:184) [dcm4chee-arc-retrieve-scp-4.4.0.Beta1.jar:]
I think this is because of configuration, maybe I have to add STORESCP as acceptedAET or similar, but I can find info on how to do it. I search through ldap using Apache Directory Studio, but I didn't find anything.
Thanks in advance.
Using dcm4che3, it goes like this if you're implementing an SCP and need to define which other SCPs are allowed to C-STORE things to you.
// Usual calamity creating Connection, ApplicationEntity and Device
...
ApplicationEntity ae = new ApplicationEntity("MYAETITLE");
String[] acceptedAETs = { "STORESCP", "GEPACS" }; // etc...
ae.setAcceptedCallingAETitles(acceptedAETs);
I assume that your favourite SCP (STORESCP) may need to know where to find the SCP known by MYAETITLE; identified by IP address and port. Typically you connect to an SCP as a SCU, issuing a C-MOVE (in the scenario laid out here) instructing the SCP to do a C-STORE to the AET identified in the C-MOVE.
I'm a bit confused by your choice of AE Title in your question (STORESCP) because that indicates that you kind of mix up the two SCPs involved here; the one receiving the C-MOVE (which should not be called STORESCP :) and the one implementing the C-STORE behaviour. The answer I gave above, is aimed at the SCP implementing the C-STORE behaviour.

ADAL 4 Android not passing client secret

I'll first say that I'm sure it is just me since people have probably got this to work out of the box without having to edit the ADAL 4 Android Library without editing the source.
When running the sample program and authenticating with a token I get an error from AZURE that it is not passing the client_secret in the message body. I can confirm that this is in fact the case - it is not passing the client_secret.
Although if I edit the OAuth2.java file and change the method buildTokenRequestMessage to something like the following the workflow works perfectly
public String buildTokenRequestMessage(String code) throws UnsupportedEncodingException {
String message = String.format("%s=%s&%s=%s&%s=%s&%s=%s&%s=%s",
AuthenticationConstants.OAuth2.GRANT_TYPE,
StringExtensions.URLFormEncode(AuthenticationConstants.OAuth2.AUTHORIZATION_CODE),
AuthenticationConstants.OAuth2.CODE, StringExtensions.URLFormEncode(code),
AuthenticationConstants.OAuth2.CLIENT_ID,
StringExtensions.URLFormEncode(mRequest.getClientId()),
AuthenticationConstants.OAuth2.REDIRECT_URI,
StringExtensions.URLFormEncode(mRequest.getRedirectUri())
// these are the two lines I've added to make it work
AuthenticationConstants.OAuth2.CLIENT_SECRET,
StringExtensions.URLFormEncode("<MY CLIENT SECRET>")
);
return message;
}
Am I doing something wrong? If not, what is the correct way to access the client secret?
My implementation is straight from the demo application with only changes being setting up the strings to match my endpoints.
Thanks
You need to register your app as a Native application at Azure AD portal. You don't need client secret for native app.

how to determine if a web service is up and running

i was trying to call the following web service from my android app, it hung then completed without returning the result:
web service:http://androidexample.com/media/webservice/JsonReturn.php
However when I clicked on the link, it worked fine - the json file displayed. yet it would not work in my app..
but now, it works fine now in my android app, perhaps it was temporarily down is what I am guessing. How can I know if a web service is up and running for an android app to consume ?
Typically, web services are designed to have a status page that can return status text or a HTTP return code to indicate service status.
If it doesn't have that, you can design a function to periodically do a very basic request with a known result to determine state. This is much better than doing a simple ping.
If it was down it would most likely show a HTML error page, which your app would try to parse, which would cause an error.
I had a similar issue, because I needed to know if the user was returning HTML or the correct JSON, to do this I created the ArrayList I was about to use outside of the try/catch of the parse area. You should do the same if you are using a string.
What I mean is, use:
ArrayList<Something> arrayList = new ArrayList<Something>();
String testString = ""; instead of String testString = null;
I was using only ArrayList<Something> arrayList; at one point which is incorrect. If the user then returns HTML, you won't get an error, the user will simply return an empty arraylist or empty string.
You can then plan for that and show some sort of error message. This way you only need one network request but you can still plan for getting the data back, and the server being down.

In java, how can I get an Amazon EC2 Instance to see its own tags?

So I have a java program running within an Amazon EC2 instance. Is there a way to programatically get its own tags? I have tried instantiating a new AmazonEC2Client to us the describeTags() function but it only gives me null. Any help would be appreciated thank you.
Edit: To make things clearer, the instances are going to be unmanned worker machines spun up to solely do some computations
This should help you get started...
String instanceId = EC2MetadataUtils.getInstanceId();
AmazonEC2 client = AmazonEC2ClientBuilder.standard()
.withCredentials(new DefaultAWSCredentialsProviderChain())
.build();
DescribeTagsRequest req = new DescribeTagsRequest()
.withFilters(new Filter("resource-id", Collections.singletonList(instanceId)));
DescribeTagsResult describeTagsResult = client.describeTags(req);
List<TagDescription> tags = describeTagsResult.getTags()
You should be able to get the current instance id by sending a request to: http://169.254.169.254/latest/meta-data/instance-id. This only works within ec2. With this you can access quite a bit of information about the instance. However, tags do not appear to be included.
You should be able to take the instance id along with the correct authentication to get the instance tags. If you are going to run this on an instance, you may want to provide an IAM user with limited access instead of a user which has access to everything in case the instance is compromised.
While using user-data may be the simplest solution, the OP was asking specifically about the tagging, and unfortunately amazon hasn't made this as easy as it could be. However, It can be done. You want to use a combination of 2 amazon services.
First you need to retrieve the Instance ID. This can be achieved by hitting the URL from within your instance:
http://169.254.169.254/latest/meta-data/instance-id
Once you have the resource ID, you'll want to use Amazon's EC2 API to access the tags. Since you said you're using Java, I would suggest the Using the AWS SDK amazon makes available. Within this SDK you'll find a method called describeTags (documentation). You can use a Resource ID as one of the filters to get the specific tags to your instance. Supported filters are
tag key
resource-id
resource-type
I suggest doing this retrieval at boot using something like cloud-init and caching the tags on your server for use later if necessary.

Trying to get InetAddress.getLocalHost.getHostAddress (Java/Scala) to return external IP

So I'm having a problem with using InetAddress.getLocalHost.getHostAddress to get the external IP address of a given machine.
I'm actually doing this in Scala in a sense - the configuration file for Akka Remote Actors default uses InetAddress.getLocalHost.getHostAddress to get the IP address of the machine, which is what I want since I will be deploying the actors on several machines. However, it seems to be returning 127.0.0.1 instead of the external IP address I want (since the remote actors need to communicate back and forth across the netwrok).
The problem is that I can't use any of the methods I've found on Google to circumvent this since they all seem to involve adjusting the code itself, whereas here I don't really have any code to adjust, the DSL just automatically uses InetAddress.getLocalHost.getHostAddress.
I've read on a few threads from a Google search that you can circumvent this by editing your host file or something? How do I do this?
Thanks!
-kstruct
You may want to use NetworkInterface class.
In particular, use static getNetworkInterfaces method to enumerate all available network interfaces.
Check your /etc/hosts file. It should map 'localhost' to 127.0.0.1 and your real hostname to your real IP address, or one of them :-| Some Linux distributions get this wrong apparently.
i got a partial solution if getLocalHost doesn't works.
this solution have the problem that you must to know the name of your network interface in order to match the real one. Maybe you can improve this code removing "virtual" devices and something else.
This is scala code, but java code is very similar
def returnInterfaceAddress() : InetAddress = {
var myInetAddress = InetAddress.getLocalHost
val interfaces : util.Enumeration[NetworkInterface] = NetworkInterface.getNetworkInterfaces()
while(interfaces.hasMoreElements){
val inter = interfaces.nextElement()
if(inter.getDisplayName() == "Realtek PCIe GBE Family Controller"){
myInetAddress = inter.getInetAddresses().nextElement()
}
}
myInetAddress
}

Categories

Resources