foundersandcoders / Live-Peers

2 stars 2 forks source link

Client side & Server side Communication Logic #30

Closed njsfield closed 7 years ago

njsfield commented 7 years ago

Overview

Simply put, our clients browsers will be firing messages back and forth between the server. For this initial application build, be using Websockets (and socket.io) as the underlying technology to carry messages.

The simple messaging operation should be as follows;

  1. Client sends a message to the server
  2. Server receives the message
  3. Server sees who the message is going to (the receiver)
  4. Server sends the message to the receiver
  5. Receiver gets the message

Then;

  1. Client receives a message from sender.
  2. Client checks to see sender is.
  3. Client decides if it would like to message back to the sender.
  4. If the Client agrees to, it should send a message etc...

The server/client technologies we're using should have abstractions so that the underlying technologies and not too closely dependent on each other:

Bad Example

Clients Direct WebSocket -> Servers Direct WebSocket -> Clients Direct WebSocket

Good Example

Clients Communication Module -> Servers Communication Module -> Clients Communication Module

This means that our application's logic is separate from the underlying technologies we're using, so that future contributors to the project can easily replace old/stagnated technology if need be.

Defining our API

1. Message Format

The messages will have lots of characteristics. One message could be for sending a simple message to a chatroom, another could be for replying to an ICE candidate. We first need to establish a consistent format that messages are sent as (so that ALL messages carry the same format when being sent).

We should organise message methods into their associated applications. An example message would be;

{
roomid  : 'fgZhaiE' // declares which global room the message should be sent to
from : 'GhisDkl' // defines an endpoint ID associated to the client
to : 'IfhSgj' // defines an endpoint ID that the client would like to send to
app : 'CHAT' // defines an application that the message applies to (another example could be RTC for messages that are specific to WebRTC communication between clients)
method : 'TEXTMESSAGE' // defines the method type in the application
params : 'Hello World' // defines the actual content of the message
}

When the client receives a message, they will simply get the following information (passed through a callback function);

2. Client communications module

The clients browser should contain a comms module to handle sending and receiving messages. The module should be a class which keeps track of;

  1. Their own endpoint(s)
  2. Their roomid(s)

And this class should have the following methods -

  1. receiveMessage. This is called when a message is received (perhaps through a websocket), when called, a handler associated to the application and method will be passed the message, and will also be passed the comms module itself if it needs to send messages back.
  2. sendMessage. This is used to send a message, and would likely be called inside an application & method handler.
  3. registerHandler This registers a function used to receive messages. The function to be registered takes several arguments; the comms module itself, the endpointId of the sender, and the contents of the message.

To see the current implementation see here

3. Client handlers

As mentioned, handlers will be used to deal with incoming messages for the client, so an example of a handler could be -

const chatRoomMessage = (comms, from, data) => {
    const msg = data.message;
    comms.send('CHAT' 'TEXTMESSAGE', from, 'I just received this message from you; ' + msg)
}

This handler will of course be registered with the comms module beforehand;

mycomms.register('CHAT', 'TEXTMESSAGE', charRoomMessage)

For this iteration of this application, we'll need the following handlers -

4. Server Comms Module

When a client first sends a message to the server, the server needs be able to work with the underlying technology used to send the message.

To allow for websockets, we need to ensure our clients websockets reaches the correct port of the server to handle them (socket.io has a simple solution to this).

We need a simple abstraction similar to this;

const serverComms = (message, rooms) => {
   message  = JSON.parse(message);
   const roomId = message.roomId;
   const from = message.from;
   const to = message.to;

   rooms[roomId].endpoints[to].socket.send(msg);

  etc etc
}

And for that to work, rooms needs to be an object to hold our endpoints. It needs to hold endpointId data and associative id used to send data to (socket.id?). So our comms module here needs to find that id and send the messages straight to it. So we need

5. Server Data Store

Our server data store should follow the form

const rooms = {
 'a34dastg44': {
    roomName='blah',
    pin='3456',
    endpoints: {
       'sdf88werwe': {
           socketid : 'towghs',
           username:'Pete',
           permissions: ['chat','av'],
     }
}

We need to build this, so that only our server comms module should interact with it. So;