Not logged in. · Lost password · Register
Forum: agsXMPP RSS
Avatar
vnorby #1
Member since Aug 2009 · 7 posts
Group memberships: Members
Show profile · Link to this post
Subject: Retrieving messages through a web client
Hello Alex and community,

First, I love the library you have built, and I wanted to let you know that we are building a Jabber/XMPP chat for our website of 4 million users using agsXMPP. (Is it the biggest implementation?) For the entire day today I've been trying to figure out why I can't get any messages to show up anywhere in the rapid prototype I'm making. I can login and logout and send a message. Ultimately, I want to long poll the received messages, but for now I'm happy just using a timed UpdatePanel so I can get a feel of sending and receiving. Here is my code:


//////////////////////Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="Default2" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Button ID="LoginButton" runat="server" Text="Login"
            onclick="LoginButton_Click" />
        <asp:Button ID="LogoutButton" runat="server" onclick="LogoutButton_Click"
            Text="Logout" />
        <br />
        <br />
        To:
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <br />
        Message:
        <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
        <br />
        <asp:Button ID="SendMessage1" runat="server" Text="Send"
            onclick="SendMessage1_Click" />
        <br />
        <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="GetMessages.aspx">Get New Messages</asp:HyperLink>
    </div>
    <asp:Label ID="Log" runat="server"></asp:Label>
    <asp:Label ID="Log2" runat="server"></asp:Label>
    <div id="chat">
    </div>
    <br />
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <asp:Timer ID="Timer1" runat="server" Interval="2000" ontick="Timer1_Tick">
            </asp:Timer>
            <asp:Label ID="Chat" runat="server" Text="Chat"></asp:Label>
        </ContentTemplate>
    </asp:UpdatePanel>
    </form>
</body>
</html>

////////////////////////Default.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using agsXMPP;
using agsXMPP.protocol.client;
using agsXMPP.Collections;
using agsXMPP.protocol.iq.roster;
using System.Threading;

public partial class Default2 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    private static XmppClientConnection xmpp;
   
    string ConstructJID(string username)
    {
        string JID = username + "@comp6";
        return JID;
    }

    public static string Username = "1";
    public static string Password = "1";

    protected void LoginButton_Click(object sender, EventArgs e)
    {
        xmpp = (XmppClientConnection)Cache["xmpp"];
        if (xmpp == null)
        {
            xmpp = new XmppClientConnection();
            Cache["xmpp"] = xmpp;
        }
        xmpp.OnLogin += new ObjectHandler(xmpp_OnLogin);
        xmpp.OnError += new ErrorHandler(xmpp_OnError);
      

        xmpp.Port = 5222;
        xmpp.UseSSL = false;
        xmpp.Server = "comp6";
        xmpp.Username = Username;
        xmpp.Password = Password;

        try
        {
            xmpp.Open();
            Log.Text = "Logged in.";
        }
        catch (Exception ex)
        {
            Log.Text = ex.Message;
        }
    }

   

    void xmpp_OnError(object sender, Exception ex)
    {
       
    }

    void xmpp_OnLogin(object sender)
    {
        xmpp.SendMyPresence();

    }
    protected void LogoutButton_Click(object sender, EventArgs e)
    {
        XmppClientConnection xmpp = (XmppClientConnection)Cache["xmpp"];

        try
        {
            xmpp.Close();
            Cache.Remove("xmpp");
            Log.Text = "Logged out.";
        }
        catch (Exception ex)
        {
            Log.Text = ex.Message;
        }
    }
    protected void SendMessage1_Click(object sender, EventArgs e)
    {
        XmppClientConnection xmpp = (XmppClientConnection)Cache["xmpp"];
        string ToUser = TextBox1.Text;
        string Message = TextBox2.Text;
        Jid ToUserJID = new Jid(ConstructJID(ToUser));
        Jid FromUserJID = new Jid(ConstructJID(Username));
        xmpp.Send(new Message(ToUserJID, MessageType.chat, Message));
        Log.Text = Username + ": " + Message;
    }
    protected void Timer1_Tick(object sender, EventArgs e)
    {
        xmpp = (XmppClientConnection)Cache["xmpp"];
        if (xmpp == null)
        {
            xmpp = new XmppClientConnection();
            Cache["xmpp"] = xmpp;
        }
        xmpp.MessageGrabber.Add(new Jid("vibhu@comp6"), new BareJidComparer(), new MessageCB(MessageCallBack), null);
    }
    protected void MessageCallBack(object sender, agsXMPP.protocol.client.Message msg, object data)
    {
        if (msg.Body == null)
        {
            return;
        }
        else
        {
            Chat.Text = msg.Body;
        }
    }
}


Forgive my spaghetti code, but any help at all would be useful.
Avatar
Alex #2
Member since Feb 2003 · 4447 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Hi  vnorby,

agsXMPP is running on the server, not on the client. Therefore the events gets raised on the server. If you debug your code you should get the OnMessage events.
When you use polling you should put all events in a collection and request them from the browser in your poll interval.

The problem here is that XMPP is async and bidirectional and your browser is only one way.

You should also consider our Silverlight library. It much easier to develop a web client with Silverlight than with asp.

Alex
Avatar
vnorby #3
Member since Aug 2009 · 7 posts
Group memberships: Members
Show profile · Link to this post
Ah, got it, thanks. Just for future people searching on this topic, you basically have to store the response from the OnMessage event handler in the cache or in some other collection on the server, as in:

void xmpp_OnMessage(object sender, Message msg)
{
if (msg.Body != null)
{
Cache["messages"] = msg.Body;
}
}

And however you are polling the results, you just poll the Cache["messages"] object instead of the actual event or handler. Thanks Alex!
Avatar
Alex #4
Member since Feb 2003 · 4447 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
correct, but there are also other events which you need to put in a collection.
You could have one collection for stanzas and add there messages, presences and iqs. When you poll then you can check whether the queued element is of type iq, message or presence.

Alex
Avatar
vnorby #5
Member since Aug 2009 · 7 posts
Group memberships: Members
Show profile · Link to this post
Yes, exactly. I completed a full, working prototype on our local network this morning. Everyone is able to see the chat bar and send and receive messages. I'm having the problem that everyone else is having, however, when I tried moving it from our local network on to our dev application server. Basically, we have a bunch of Windows 2003 servers and database servers over at Rackspace where we run some of our services. I installed our Openfire server on one of the machines there and configured it exactly as I had configured it on our local network. When we want to access the services, we open up a VPN connection to our Rackspace farm. The openfire server and computer network name are both chat-server-dev, and the IP address that we use to access it locally is 192.168.100.20. When I open Spark, I type in a username, password, and 192.168.100.20 as the server. This connects and logs in perfectly fine. It also works if I put in chat-server-dev as the server, and 192.168.100.20 as the connect server. Everything is on port 5222. Unfortunately, it's no longer connecting in the client, even when I tried the fixes you have continuously posted on this forum. I have set the Server as chat-server-dev and 192.168.100.20 as the ConnectServer. I have switched them around. I've made sure that AutoResolveConnectServer is false.

I wonder if it has something to do with being on VPN? We are using the VPN as opposed to opening up ports and accessing the dev box externally, which we will try tomorrow, but I was wondering if you had any insights on this problem.

Thanks again, Alex.
Avatar
Alex #6
Member since Feb 2003 · 4447 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Please post your Xml Log if there is any.
This can be also a IPV4/V6 issue like discussed here often in the forums.

Alex
Avatar
vnorby #7
Member since Aug 2009 · 7 posts
Group memberships: Members
Show profile · Link to this post
When we put it on an external public machine with the firewall turned off, it works again. I had to put the IP as the ConnectServer and the server name as the Server. It wouldn't work without that. But I think it was just the firewall (even though it shouldn't encounter it over a VPN connection) giving me the problem with our Rackspace machine. It could also be an IPV6 issue, though. I know that's enabled on my Vista machine and on the external server, but I'm not sure about the Rackspace one.
Avatar
Alex #8
Member since Feb 2003 · 4447 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
great, so I assume your problem is fixed now.

Alex
Avatar
vnorby #9
Member since Aug 2009 · 7 posts
Group memberships: Members
Show profile · Link to this post
So I was able to get it up and test it with some of our users today (about 30 or 40 concurrent). Everything works fine, sending/receiving/presence, but every 5-10 minutes the server crashes and resets itself when it gets this error:


An unhandled exception occurred and the process was terminated.

Application ID: /LM/W3SVC/1/ROOT

Process ID: 3976

Exception: System.InvalidOperationException

Message: EndRead can only be called once for each asynchronous operation.

StackTrace:    at System.Net.Security._SslStream.EndRead(IAsyncResult asyncResult)
   at agsXMPP.net.ClientSocket.EndReceive(IAsyncResult ar)
   at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
   at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
   at System.Net.FixedSizeReader.ReadCallback(IAsyncResult transportResult)
   at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.ContextAwareResult.Complete(IntPtr userToken)
   at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
   at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
   at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

Do you have any intuition as to what this might be?
Avatar
vnorby #10
Member since Aug 2009 · 7 posts
Group memberships: Members
Show profile · Link to this post
I'm occasionally getting the following error, and then following this one comes the last error I posted about 5-10 minutes later.

An unhandled exception occurred and the process was terminated.

Application ID: /LM/W3SVC/1/ROOT

Process ID: 5440

Exception: System.NotSupportedException

Message: The BeginRead method cannot be called when another read operation is pending.

StackTrace:    at System.Net.Security._SslStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security._SslStream.BeginRead(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback asyncCallback, Object asyncState)
   at agsXMPP.net.ClientSocket.Receive()
   at agsXMPP.net.ClientSocket.EndReceive(IAsyncResult ar)
   at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.ContextAwareResult.Complete(IntPtr userToken)
   at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
   at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
   at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.
Avatar
Alex #11
Member since Feb 2003 · 4447 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
I think we solved the problem yesterday by phone.
Let me know if its fixed now, and what the final solution was.

Thanks,
Alex
Avatar
vnorby #12
Member since Aug 2009 · 7 posts
Group memberships: Members
Show profile · Link to this post
Thanks, yeah. Sorry about the call - this is a huge release for us.

Basically, the problem was with our auto-registration system. As in, when the user fails to authorize, it calls a new register handler and registers a new account for them and logs them in.

The problem seemed to be with calling the open method on the xmpp connection object twice with the same properties. Although it never threw any exceptions using it with just a few people, I think that at random points the login and registration were happening on the same connection at the same time and the connection objects were stepping on each other. The solution was to forcibly kill everything having to do with the xmpp object before trying to register new accounts - i.e. trying to call the close method, trying to stop the event handlers, removing the cached xmpp object, and only registering a new account when we were for sure that there was nothing from the previous login attempt left over.
Close Smaller – Larger + Reply to this post:
Verification code: VeriCode Please enter the word from the image into the text field below. (Type the letters only, lower case is okay.)
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Special characters:
Forum: agsXMPP RSS