Skip to content
leecher1337 edited this page May 13, 2015 · 1 revision

Synchronizing Messages

On startup, the client can ask the server if there are any missed messages stored on the server. As MSN is capable of being used on multiple clients, different clients may have different synchronisation states of history. In order to receive offline messages, this step is necessary even if you don't want to sync history. Therefore the client should check if it knows since when messages need to be fetched. A simple strategy would be to check the DB for the last timestamp an event occured with this protocol. As always, the timestamp is a UNIX timestamp in ms.

Fetching recent conversations

The client then sends the following sync-Request to the server to retrieve the most recent messages. Only the last message for every contact that occured is being sent, you need to fetch the full history per contact in a later step. The client sends:

GET 12 MSGR\RECENTCONVERSATIONS 517
Registration: ...base64 registration...

<recentconversations><start>1428249688000</start><pagesize>100</pagesize></recentconversations> 

Where start is the UNIX timestamp in ms since when events should be sent. The server replies to that with:

<recentconversations-response>
  <conversations>
    <conversation>
      <id>8:live:user1</id> 
      <version>1430489866083</version> 
      <properties>
        <consumptionhorizon>1430404148000;1430489865000;10156429743073042633</consumptionhorizon> 
      </properties>
      <options /> 
      <messages>
        <message>
          <messageid>1430300402349</messageid> 
          <originalarrivaltime>2015-04-29T09:36:41.592Z</originalarrivaltime> 
          <from>8:live:user1;epid={00155193-decb-dc89-95e0-43bd987ed463}</from> 
          <messagetype>Text</messagetype> 
          <content>my message</content> 
          <clientmessageid>5120743105835678321</clientmessageid> 
          <composetime>2015-04-29T09:36:41.592Z</composetime> 
        </message>
      </messages>
    </conversation>
    <conversation>
      <id>8:live:user2</id> 
      <version>1430485886314</version> 
      <properties>
        <consumptionhorizon>1429961225000;1429984818000;3932865346765530604</consumptionhorizon> 
      </properties>
      <options /> 
      <messages>
        <message>
          <messageid>1430300404679</messageid> 
          <originalarrivaltime>2015-05-01T13:11:26.178Z</originalarrivaltime> 
          <from>8:live:user2;epid={ee155593-eeca-da89-95f0-46bd987ed489}</from> 
          <messagetype>RichText</messagetype> 
          <content>hi there! &lt;ss type="smile"&gt;:)&lt;/ss&gt;</content> 
          <clientmessageid>5137215689534566412</clientmessageid> 
          <composetime>2015-05-01T13:11:26.178Z</composetime> 
        </message>
      </messages>
    </conversation>
    <conversation>
      <id>19:[email protected]</id>
      <version>1430775110903</version>
      <properties />
      <options />
      <messages>
        <message>
          <messageid>1430768120706</messageid>
          <originalarrivaltime>2015-05-04T21:31:50.903Z</originalarrivaltime>
          <from>19:[email protected]</from>
          <messagetype>ThreadActivity/DeleteMember</messagetype>
          <content>&lt;deletemember&gt;&lt;eventtime&gt;1430775111792&lt;/eventtime&gt;&lt;initiator&gt;8:live:user1&lt;/initiator&gt;&lt;target&gt;8:live:user2&lt;/target&gt;&lt;/deletemember&gt;</content>
          <composetime>2015-05-04T21:31:50.903Z</composetime>
        </message>
      </messages>
      <thread>
        <lastjoinat>1430661534162</lastjoinat>
        <version>1430775110903</version>
        <topic>live:user1, live:user2</topic>
      </thread>
    </conversation>
  </conversations>
  <syncstate>12406b7d754c01000000000000000000003b4b87c6d6cc4d250b0000006c656563686572313333378bc4860a410100000100000000000000007f33fc0f4d01000001406b7d754c0100007f33fc0f4d0100000100000000000000007f33fc0f4d01000001406b7d754c0100007f33fc0f4d0100000000000000000000</syncstate> 
  <hasmore>False</hasmore> 
</recentconversations-response>

So as you can see, there are not only messages from/to users in it but also from groupchats. And there are different message types. Some of them are already known from groupchats-documentation. The <content> of them is the same as the XML that gets sent on groupchat notifications, so the client can conveniently feed them into the same processing routine.

Fetching messages for a contact stored on the server

To get the full history of a contact beginning with a certain timestamp (I think maximum is 2 weeks in the past, Server doesn't have more backlog at least on consumed messages), the client has to isse a <messagesbyconversation> request:

GET 15 MSGR\MESSAGESBYCONVERSATION 548
Registration: ...base64 registration...

<messagesbyconversation>
  <id>8:live:user1</id>
  <start>1428249689000</start>
  <pagesize>100</pagesize>
</messagesbyconversation> 

This pulls all messages that start at a given timestamp (unixtime in ms, as always), as long as the server has them still available. Please note, that messages are being sent in reverse order, so the newest messages come first! The server replies with:

<messagesbyconversation-response>
  <id>8:live:user1</id>
  <messages>
    <message>
      <messageid>1429962782814</messageid>
      <originalarrivaltime>2015-04-25T11:53:02.852Z</originalarrivaltime>
      <from>8:live:user1;epid={00155193-decb-dc89-95e0-43bd987ed463}</from>
      <messagetype>Text</messagetype>
      <content>&lt;hellooo&gt;</content>
      <clientmessageid>6141646244149221670</clientmessageid>
      <composetime>2015-04-25T11:53:02.852Z</composetime>
    </message>
    <message>
      <messageid>1429961236525</messageid>
      <originalarrivaltime>2015-04-25T11:27:16.961Z</originalarrivaltime>
      <from>8:live:user2;epid={ee155593-eeca-da89-95f0-46bd987ed489}</from>
      <messagetype>RichText</messagetype>
      <content>hi there! &lt;ss type="smile"&gt;:)&lt;/ss&gt;</content>
      <clientmessageid>17625830632587334299</clientmessageid>
      <composetime>2015-04-25T11:27:16.961Z</composetime>
    </message>
  </messages>
  <messagessyncstate>123000000031393a3938383063313965643139623463306639313930346636393739656261306235407468726561642e736b79706501bc31d0194d0100000e0fd4194d01000000</messagessyncstate> 
  <hasmore>False</hasmore> 
</messagesbyconversation-response>

Here is a sample for a Groupchat. You can find the various messagetypes of groupchat on the Groupchat documentation:

<messagesbyconversation-response>
  <id>19:[email protected]</id>
  <messages>
    <message>
      <messageid>1430757437454</messageid>
      <originalarrivaltime>2015-05-03T12:50:37.454Z</originalarrivaltime>
      <from>19:[email protected]</from>
      <messagetype>ThreadActivity/DeleteMember</messagetype>
      <content>&lt;deletemember&gt;&lt;eventtime&gt;1430657438265&lt;/eventtime&gt;&lt;initiator&gt;8:live:user1&lt;/initiator&gt;&lt;target&gt;8:live:user1&lt;/target&gt;&lt;/deletemember&gt;</content>
      <composetime>2015-05-03T12:50:37.454Z</composetime>
    </message>
    <message>
      <messageid>1430757238975</messageid>
      <originalarrivaltime>2015-05-03T12:47:18.975Z</originalarrivaltime>
      <from>19:[email protected]</from>
      <messagetype>ThreadActivity/TopicUpdate</messagetype>
      <content>&lt;topicupdate&gt;&lt;eventtime&gt;1430657239224&lt;/eventtime&gt;&lt;initiator&gt;8:live:user1&lt;/initiator&gt;&lt;value&gt;And this is the new chat topic&lt;/value&gt;&lt;/topicupdate&gt;</content>
      <composetime>2015-05-03T12:47:18.975Z</composetime>
    </message>
    <message>
      <messageid>1430757193953</messageid>
      <originalarrivaltime>2015-05-03T12:46:33.953Z</originalarrivaltime>
      <from>19:[email protected]</from>
      <messagetype>ThreadActivity/AddMember</messagetype>
      <content>&lt;addmember&gt;&lt;eventtime&gt;1430657193953&lt;/eventtime&gt;&lt;initiator&gt;8:live:user1&lt;/initiator&gt;&lt;target&gt;8:live:user2&lt;/target&gt;&lt;/addmember&gt;</content>
      <composetime>2015-05-03T12:46:33.953Z</composetime>
    </message>
  </messages>
  <messagessyncstate>123000000031393a3938383063313965643139623463306639313930346636393739656261306235407468726561642e736b79706501bc31d0194d0100000e0fd4194d01000000</messagessyncstate>
  <hasmore>False</hasmore>
</messagesbyconversation-response> 

It can be seen that the <from> handle is always equivalent to the ID of the groupchat whereas the original sender and target is coded in the <content> member the same way as it is with groupchat messages, so this can be processed by the same routine.

The most XML tags are self-explantory, one tag that is important to have a look at is the <hasmore> tag. If it is set to true, there are more messages available to be fetched. To get them, issue the same request as the initial one to get the messages but also specify the <messagessyncstate> the client received:

GET 15 MSGR\MESSAGESBYCONVERSATION 548
Registration: ...base64 registration...

<messagesbyconversation>
  <id>8:live:user1</id>
  <start>1428249689000</start>
  <messagessyncstate>123000000031393a3938383063313965643139623463306639313930346636393739656261306235407468726561642e736b79706501bc31d0194d0100000e0fd4194d01000000</messagessyncstate>
  <pagesize>100</pagesize>
</messagesbyconversation> 

The answer you receive is in the same layout as above. You can keep fetching as long as is true to pull the recent conversations from the server. It is assumed that the same applies to the <recentconversations> polling, but currently this couldn't be verified, as this never occured in the tests so far.