Service Unavailable 503 Error during File Transfer with Openfire using Smack - xmpp

I am trying to send a file through chat using openfire on the server and the smack java library.
This is the output I get:
Status :: Error Error :: null Exception :: service-unavailable(503) Is
it done? true
Here are my sender and receiver functions:
public void fileTransfer(String fileName, String destination) throws XMPPException {
// Create the file transfer manager
FileTransferManager manager = new FileTransferManager(connection);
FileTransferNegotiator.setServiceEnabled(connection,true);
// Create the outgoing file transfer
OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer(destination);
// Send the file
transfer.sendFile(new File(fileName), "You won't believe this!");
try {
Thread.sleep(10000);
}
catch(Exception e){}
System.out.println("Status :: " + transfer.getStatus() + " Error :: " + transfer.getError() + " Exception :: " + transfer.getException());
System.out.println("Is it done? " + transfer.isDone());
}
public void fileReceiver(final boolean accept, final String fileName) {
// Create the file transfer manager
final FileTransferManager manager = new FileTransferManager(connection);
// Create the listener
manager.addFileTransferListener(new FileTransferListener() {
public void fileTransferRequest(FileTransferRequest request) {
// broadcast something here. Wheather users want to accept file
// Check to see if the request should be accepted
if(accept) {
// Accept it
IncomingFileTransfer transfer = request.accept();
try {
transfer.recieveFile(new File(fileName));
System.out.println("File " + fileName + "Received Successfully");
//InputStream input = transfer.recieveFile();
} catch (XMPPException ex) {
Logger.getLogger(XmppManager.class.getName()).log(Level.SEVERE, null, ex);
}
} else {
// Reject it
request.reject();
}
}
});
}

I had same problem, I investigated the stanza and solved it this way.
Many people use "/Smack" or "/Resource" as resource part in jid, but that can be done another way.
Resource path is changing with every presence changed of user. Lets say we want to send image to this user:
"user1#mydomain"
You must add "/Resource" part to this jid and it become this:
user1#mydomain/Resource
But /Resource path is changing with presence so you must follow every presence change to update resource path.
Best way is to get user presence is in roster listener and in presencheChanged() method you get last user resource part like this:
Roster roster=getRoster();
roster.addRosterListener(new RosterListener() {
#Override
public void entriesAdded(Collection<Jid> addresses) {
Log.d("entriesAdded", "ug");
context.sendBroadcast(new Intent("ENTRIES_ADDED"));
}
#Override
public void entriesUpdated(Collection<Jid> addresses) {
Log.d("entriesUpdated", "ug");
}
#Override
public void entriesDeleted(Collection<Jid> addresses) {
Log.d("entriesDeleted", "ug");
}
#Override
public void presenceChanged(Presence presence) {
Log.d("presenceChanged", "ug");
//Resource from presence
String resource = presence.getFrom().getResourceOrEmpty().toString();
//Update resource part for user in DB or preferences
//...
}
});
}
Resource string will be some generated string like "6u1613j3kv" and jid will become:
user1#mydomain/6u1613j3kv
That means that you must create your outgoing transfer like this:
EntityFullJid jid = JidCreate.entityFullFrom("user1#mydomain/6u1613j3kv");
OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer(jid)
transfer.sendFile(new File("DirectoryPath"), "Description");
And that is how i have solved my problem with file transfer on smack and Openfire.
In your case jid is destination.
Also to mention you must add following properties in your Openfire server:
xmpp.proxy.enabled - true
xmpp.proxy.externalip - MY_IP_ADDRESS
xmpp.proxy.port - 7777
Just to mention, I am using Openfire 4.0.2 and Smack 4.2.2.
Also this can be configured the easy way, just set the resource on
XMPPTCPConnectionConfiguration.Builder .
like
XMPPTCPConnectionConfiguration.Builder configurationBuilder =
XMPPTCPConnectionConfiguration.builder();
configurationBuilder.setResource("yourResourceName");

Related

How would I receive all fields from a dynamic form with Struts?

I found myself with the following problem:
I have a page generated with logic:iterate that shows the current supervisor and assistant of a service.
That page also acts as a form where people can add their possible substitutes, but you never know how many of those are there.
Due to the environment I am currently working with it had to be without JSTL so a lot of options were gone; couldn't get DynaActionForm working for this either.
Since I couldn't find anything but I already got the answer I decided to create this to answer anyone who might have the same issue.
Code:
public ActionForward post(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
String[] tot;
try {
Enumeration<?> fieldsForm = request.getParameterNames();
while(fieldsForm.hasMoreElements()) {
String current = (String) fieldsForm.nextElement();
tot = request.getParameterValues(current);
System.out.println("Field name is: " + current);
for (i=0; i<tot.length; i++) {
// do whatever you need to do; contents are in tot[i]
System.out.println("Value " + i + " is: " + tot[i]);
}
}
catch (Exception ex) {
ex.printStackTrace();
System.err.println(ex.getMessage());
}
}

GCM Cloud Connection Server doesn't respond to SASL on XMPP

Using agsXMPP to connect to Google Cloud Messaging XMPP API for the purpose of sending notification to Android devices.
The connection is established OK, but on SASL start, after sending the PLAIN auth element, the server stops responding, and closes the connection after a further 20 seconds.
Base64 decoding the auth example from the documentation page (http://developer.android.com/google/gcm/ccs.html) shows login values of:
126200347933#projects.gcm.android.com12620034793#projects-ga-.android.comAIzaSyB3rcZNkfnqKdFb9mhzCBiYpORDA2JWWtw
Where as agsXMPP is (correctly I think) encoding the string, to give something like:
[ProjectID]\40gcm.googleapis.com[**API*KEY*PASSWORD**]
Note the \40 in my version instead of the # in the Google example - could this make a difference?
I'm expecting either a success or failure message, no response at all is difficult to debug. Could this at character be responsible for some failure, or does Google's implementation of XMPP just not provide the correct responses.
UPDATED:
I answered below, essentially, yes, Google can't handled the encoded # character because it doesn't support that XMPP extension.
After some more testing, I added a new SaslFactory mechanism in agsXMPP and bound it to use the username without encoding (part of extension http://xmpp.org/extensions/xep-0106.html, which Google doesn't support), and then on SaslStartEvent - specify that I want to use that mechanism instead of the inbuilt plain one. - and now the connection will continue normally.
xmpp = new XmppClientConnection();
xmpp.UseSSL = true;
xmpp.UseStartTLS = false;
xmpp.Server = "gcm.googleapis.com";
xmpp.ConnectServer = "gcm.googleapis.com";
xmpp.Port = 5235;
/* Other connection settings /*
SaslFactory.AddMechanism("MyPLAINMechanism", typeof(MyPlainMechanismClass));
xmpp.OnSaslStart += (sender, args) =>
{
args.Auto = false;
args.Mechanism = "MyPLAINMechanism";
args.ExtentedData = new GcmPlainSaslExtendedData
{
Username = "MY UNENCODED USERNAME"
};
};
Then we define the MyPlainMechanismClass which inherits from the Mechanism in agsXMPP, the source code is the same as the original PlainSaslMechanism except the line where the username is input - you can pass in an unencoded username using the ExtendedData property on args.
public class MyPlainMechanismClass: Mechanism
{
private XmppClientConnection m_XmppClient = null;
public GcmPlainSaslMechanism()
{
}
public override void Init(XmppClientConnection con)
{
m_XmppClient = con;
// <auth mechanism="PLAIN" xmlns="urn:ietf:params:xml:ns:xmpp-sasl">$Message</auth>
m_XmppClient.Send(new agsXMPP.protocol.sasl.Auth(agsXMPP.protocol.sasl.MechanismType.PLAIN, Message()));
}
public override void Parse(Node e)
{
// not needed here in PLAIN mechanism
}
private string Message()
{
// NULL Username NULL Password
StringBuilder sb = new StringBuilder();
//sb.Append( (char) 0 );
//sb.Append(this.m_XmppClient.MyJID.Bare);
sb.Append((char)0);
//sb.Append(this.Username);
sb.Append(((GcmPlainSaslExtendedData) this.ExtentedData).Username);
sb.Append((char)0);
sb.Append(this.Password);
byte[] msg = Encoding.UTF8.GetBytes(sb.ToString());
return Convert.ToBase64String(msg, 0, msg.Length);
}
}
Our custom ExtendedData object which we use to pass in custom arguments, such as an unencoded username in this case.
public class GcmPlainSaslExtendedData : agsXMPP.Sasl.ExtendedData
{
public string Username { get; set; }
}

How to fetch data of remote server in GWT development mode?

I'm a GWT beginner. I debug my program in GWT development mode. The url is http://127.0.0.1:8888/Replayer.html?gwt.codesvr=127.0.0.1:9997.
I want to get data from existing server which provided data in json format. My code is:
String url = "http://i.abc.com?sid=" + mSessionId + "&action=info";
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL.encode(url));
try {
Request request = builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
// Couldn't connect to server (could be timeout, SOP
// violation, etc.)
Window.alert("Get fudao info error");
mPrepare = false;
}
#Override
public void onResponseReceived(Request request, Response response) {
GWT.log("statuscodeļ¼š"+response.getStatusCode());
if (200 == response.getStatusCode()) {
// Process the response in response.getText()
Window.alert(response.getText());
mPrepare = true;
} else {
// Handle the error. Can get the status text from
// response.getStatusText()
Window.alert("Get fudao info wrong");
mPrepare = false;
}
}
});
} catch (RequestException e) {
// Couldn't connect to server
}
When run the application, the request failed and its status was "canceled". Is it the reason that I cannot request remote server address from localhost for SOP restrictions?
How to fetch data of remote server in GWT development mode?
Normally can't fetch data from another server form GWT client code. But your local server can serve as proxy, e.g. you sending request to your local server, it will send request to remote server, than it will get response from remote server and give it to the GWT client code. This is basically the easiest solution.

How to retrieve Someone's Avatar/Photo with agsXmpp

this is what I have so far:
void xmppConnection_OnReadXml(object sender, string xml)
{
if (xml.Contains(XmlTags.PhotoOpen))
{
int startIndex = xml.IndexOf(XmlTags.PhotoOpen) + XmlTags.PhotoOpen.Length;
int length = xml.IndexOf(XmlTags.PhotoClose) - startIndex;
string photoHash = xml.Substring(startIndex, length);
}
}
I guess I can't undo the hash, but I want to the get a person's avatar/photo. How do I achieve this?
You need to handle the VCard events and responses from XMPP connection:
private void vcardToolStripMenuItem_Click(object sender, EventArgs e)
{
RosterNode node = rosterControl.SelectedItem();
if (node != null)
{
frmVcard f = new frmVcard(node.RosterItem.Jid, XmppCon);
f.Show();
}
}
The above is from the miniclient solution example from the AGSXMPP download. Note, it happens when a user request a VCARD for a user. You can initiate that request whenever you want, however.
private void VcardResult(object sender, IQ iq, object data)
{
if (InvokeRequired)
{
// Windows Forms are not Thread Safe, we need to invoke this :(
// We're not in the UI thread, so we need to call BeginInvoke
BeginInvoke(new IqCB(VcardResult), new object[] { sender, iq, data });
return;
}
if (iq.Type == IqType.result)
{
Vcard vcard = iq.Vcard;
if (vcard!=null)
{
txtFullname.Text = vcard.Fullname;
txtNickname.Text = vcard.Nickname;
txtBirthday.Text = vcard.Birthday.ToString();
txtDescription.Text = vcard.Description;
Photo photo = vcard.Photo;
if (photo != null)
picPhoto.Image = vcard.Photo.Image;
}
}
}
That is what happens when someone requests the VCARD information from XMPP and the IQ type matches the proper data. You can thenpull the photo from vcard.Photo.
You trigger the pull with:
VcardIq viq = new VcardIq(IqType.get, new Jid(jid.Bare));
con.IqGrabber.SendIq(viq, new IqCB(VcardResult), null);
The first line there is the request to the XMPP server, that the VCARD form uses to request user information.
The second line there, sets up another grabber (callback of sorts), that the form uses to wait for the information to arrive, and then parse out the necessary information. IN this case, the grabber is in a new form, so that the main application doesn't have to worry about parsing that information.
You can look at the entire source by extracting the AGSXMPP zip file to your local drive, and looking in the Samples\VS2008\miniclient folder.
You can click link:http://forum.ag-software.de/thread/192-How-to-save-vcard-data

Calling remote Servlet from GWT

I am trying to call remote servlet from GWT, actually the GWT-RPC doesn't seems to work, so I am trying to do it using the RequestBuilder.
Here's the code snippet:
String url = "http://some-remote-host:8888/GWTJSTest/SomeServlet?name=" + textBox.getText();
RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET, url);
// requestBuilder.setHeader("Origin", "*");
// requestBuilder.setHeader("Access-Control-Allow-Origin", "*");
try
{
requestBuilder.sendRequest(null, new RequestCallback()
{
public void onResponseReceived(Request request, Response response)
{
if (response.getStatusCode() == 200)
{
Window.alert(response.getText());
}else
{
Window.alert(response.getText() + " : " + response.getStatusCode() + response.getStatusText());
}
}
public void onError(Request arg0, Throwable arg1)
{
Window.alert(arg1.toString());
}
});
} catch (RequestException e)
{
Window.alert("CATCH BLOCK: " + e.getMessage());
e.printStackTrace();
}
Actually, IE8 returns the data but after a warning message, but Firefox doesn't! Why is this?
As you see, I am trying to set some request headers but no way.
If you're trying to make a request to your own server and port (the same one that your GWT page is on), replace the first line with:
String url = "/GWTJSTest/SomeServlet?name=" + textBox.getText();
If you're trying to talk to a different server, or a different port on your own server, the Same Origin Policy will keep you from doing that. You'll need to proxy it from your own server.
The remote servlet is the one that needs to set the CORS header that you have:
Access-Control-Allow-Origin: *
Alternatively you can specify just your own domain instead of * if you don't want other domains interacting with the remote servlet.
I've added :
<add-linker name="xs" /> to .gwt.xml
And then replaces GWT-PRC by JsonpRequestBuilder (transforming JSONP between the server and the client)