Communicating between (chat) server and client - network-programming

just to clarify certain questions.
Let's say I'm making a chat application. Most of the online tutorials are basic server-client programs that send the chat message directly as strings.
So what if there is someone that came online, or offline. How would the client notify the server of such changes? What I came up with is to use flags {online}User, {offline}user, {privatechat}blabla.
What if someone knew how your code and that would allow them to sabotage by keep sending {online}blabla.
This would work, but has some flaws that I could think of as well. What would be the correct or better way to do this?
Can someone point me in the right direction? Thanks.
Or another example, in games. To tell the unit to move right, does it send a string back to the server {unit}{move right}? Something along those lines.
I kinda got the logic on how to make the chat server. If I just prefix a "{chat}" to the textbox. As long as I read this command "{chat}" I'll just ignore whichever commands which comes along.
How about in an RTS (not that I'm gonna make one, just curious), you mean there's literally 50 over strings telling how units move, attack, take damage, actions etc? Will all these commands be done on one thread? or multi-threaded?

Well you have to implement session-handling and send sessionToken with your order to move a unit in game. So server will be able to check whether pointed user have rights to order the pointed unit etc. Same things with chats.
In my chat, every client sends some PING message to server every two minutes. So if 5 minutes passed and no PING is received, server counts the user as [offline].
If you are afraid of cheating users who reverse engineer your client and can make serious troubles to the system with cheats, you have to do two things:
make server to check if given
user order is valid
implement bot-detection. check if
user makes some actions with some
constant time interval or if user
uses some limited amount of words in
chat etc.
I hope this post at least gives you some point.
The example of server logic is following:
[WebMethod]
string LoginUser(string login, string pwd)
{
if( dal.IsCorrectUser(login,pwd) )
{
string token = dal.MakeSession(login);
return string;
}
return "-1";
}
[WebMethod]
bool UserOrder(string token, string order)
{
if( !dal.SessionExist(token) )
{
return false;
}
int userId = dal.GetUserBySession(token);
if(! dal.ValidOrderForUser(userId,order) )
{
dal.RegisterWrongOrder(userid,order); // For cheaters-detecting purposes
return false;
}
return dal.ExecuteUserOrder(userId, order);
}
In fact you can send string or any serializable objects as an user-order.
[Serializable]
struct UserOrder
{
int unitId;
int Order;
}
All samples are for c#. Just to demonstrate logic.

Related

Managing Server Side Events with a Service Worker

I am building a web app to display on my iPad to control my raspberry pi acting as an audio recorder. Part of the need is to maintain an event source open so that the server can send Server Side Events. A specific instance of the app can grab control of the recording process, but will loose control if the server sees sse link closes. This is just protection against a client disappearing and leaving the control held (control of the process does needed to be renewed at least every 5 minutes - but I don't really want to wait that long in the normal case of someone just closing the browser tab.)
Part of my need is to push the browser to the background so I can then open up the camera and record a video.
I built this app and had it almost working see https://github.com/akc42/pi_record.git (master branch).
Until I pushed the browser to the background and found IOS shut down the page and broke the sse link.
I tried restructuring to use a private web worker to manage the sse link, massing messages between the web worker and the main javascript thread - again almost working (see workers branch of above repository). But that got shutdown too!
My last thought is to use a service worker, but how to structure the app?
Clearly the service worker must act as a client to the server for the server side events. It must keep the connection open, but it also needs to keep track of multiple tabs in the browser which may or may not try and grab control of the interface, and only allow one tab to do so.
I can think of three approaches - but its difficult to see which is better. At least I have never even seen any mention of approach 2 and 3 below , but it seems to me that one of these two might actually be the simplest.
Approach 1
Move the code I have now for separate web workers into the service worker. However we will need to add to the message passing some form of ID between window and service. So I can record which tab actually grabbed control of the interface and therefore exclude other tabs from doing so (ie simulate a failed attempt to take control).
As far as I can work out MessageEvent.ports[0] could be a unique object which I could store in a Map somewhere, but I am not entirely convinced that the MessageChannel wouldn't close if the browser moved to the background.
Approach 2
have a set of phantom urls in the service worker that simulate all the different message types (and parameters) that where previously sent my the tab to its private web worker.
The fetch event provides a clientid (which I can use to difference between who actually grabbed control) and which I can use to then do Clients.get(clientid).postMessage() (or Clients.matchAll when a broadcast response is needed)
Code would be something like
self.addEventListener('fetch', (event) => {
const requestURL = new URL(event.request.url);
if (/^\/api\//.test(requestURL.pathname)) {
event.respondWith(fetch(event.request)); //all api requests are a direct pass through
} else if (/^\/service\//.test(requestURL.pathname)) {
/*
process these like a message passing with one extra to say the client is going away.
*/
if (urlRecognised) {
event.respondWith(new Response('OK', {status: 200}));
} else {
event.respondWith(new Response(`Unknown request ${requestURL.pathname}`, {status: 404}));
}
} else {
event.respondWith(async () => {
const cache = await caches.open('recorder');
const cachedResponse = await cache.match(event.request);
const networkResponsePromise = fetch(event.request);
event.waitUntil(async () => {
const networkResponse = await networkResponsePromise;
await cache.put(event.request, networkResponse.clone());
});
// Returned the cached response if we have one, otherwise return the network response.
return cachedResponse || networkResponsePromise;
});
}
});
The top of the the fetch event just passes the standard api requests made by the client straight through. I can't cache these (although I could be more sophisticated and perhaps pre reject those not supported).
The second section matches phantom urls /service/something
The last section is taken from Jake Archibald's offline cookbook and tries to use the cache, but updates the cache in the background if any of the static files have changed.
Approach 3
Similar to the approach above, in that we would have phantom urls and use the clientid as a unique marker, but actually try and simulate a server side event stream with one url.
I'm thinking the code with be more like
...
} else if (/^\/service\//.test(requestURL.pathname)) {
const stream = new TransformStream();
const writer = stream.writeable.getWriter();
event.respondWith(async () => {
const streamFinishedPromise = new Promise(async (resolve,reject) => {
event.waitUntil(async () => {
/* eventually close the link */
await streamFinishedPromise;
});
try {
while (true) writer.write(await nextMessageFromServerSideEventStream());
} catch(e) {
writer.close();
resolve();
}
});
return new Response(stream.readable,{status:200}) //probably need eventstream headers too
}
I am thinking that approach 2 could be the simplest, given where I am now but I am concerned that I can see nothing when searching for how to use service workers that discusses this phantom url approach.
Can anyone comment on any of these approaches and provide guidance on how to best program the tricky bits (for instance does Approach 1 message channel close when the browser is moved to the background on an iPad, or how do you really keep a response channel open, and does that get closed when the browser moves to the background in Approach 3)
The simple truth is that none of these approaches will work. What I didn't realise when I asked the question is that a service worker is re-run by the browser when ever there is something to do and that run only lasts for the length of time of the processing of an event. Although eventWaitUntil can prolong that, the only reference to how long I can find is that the browser is still at liberty to cancel it if it appears it might never close. I can't imagine than in a period of several hours it won't get cancelled. So an Event Source will close effectively terminate its link to the server.
So my only option to achieve what I want is to have the server carry on when the Event Source closes and find some other mechanism to release resources held on behalf of the client

Nexmo - Select from number based on location of destination to number

In Twilio there's an concept of phone # pools. A txt message can be sent using this Pools Id value and Twilio will select the best FROM number to send with. I've looked around Nexmos API's and I don't see similar capabilities, is this possible?
The only other option I've found is something call applications but I can't send messages without manually selecting the from numbers instead of automating it via application Id, I assume that would be one of the 'use cases'
There's a document from Nexmo https://help.nexmo.com/hc/en-us/articles/217571017-What-is-a-Sender-ID- that has the following
Random Numeric - Nexmo will apply a random number to comply with local regulations (usually taken from a pool of numbers we have access to from the relevant destination market).
Problem is how do I configure Random Numeric? It doesn't really explain and I might have missed those docs. Any suggestion help.
Random numeric is not something you set, is something the Nexmo API does in order to ensure delivery in certain parts of the world, in order to conform with local regulations.
There is no Pools concept in Nexmo at the moment, so if you want the same functionality you'd have to build it in your code. Rent a bunch of Nexmo phone numbers, and then apply a random algorithm of choice in your code before sending each message to select your phone number. Something like:
let myNexmoNumbers = [447481234567, 447481234568, 447481234569]
nexmo.message.sendSms(myNexmoNumbers[Math.floor(Math.random() * myNexmoNumbers.length)], TO_NUMBER, TEXT_MESAGE, (err, responseData) => {
if (err) {
console.log(err);
} else {
if(responseData.messages[0]['status'] === "0") {
console.log("Message sent successfully.");
} else {
console.log(`Message failed with error: ${responseData.messages[0]['error-text']}`);
}
}
})

The reason why gRPC streaming services can only have a single parameter

At the moment, gRPC service definitions can only have a single parameter even if it’s a streaming service which makes challenging to represent the “initial” request. For instance, consider a chat app in which a user can join a chat room.
In this case, the domain can be modelled as follows.
message JoinRoomRequest {
required string room = 1;
}
message ChatMessage {
required string content = 2;
}
A consumer of the chat app would send a join request and start a bi-directional stream of messages, so the service can be described in this way.
service SimpleChat {
rpc joinChatRoom (JoinRoomRequest, stream ChatMessage) returns (stream ChatMessage);
}
However, in gRPC the above syntax is not valid. The only way to represent the described chat service is
service SimpleChat {
rpc joinChatRoom (stream ChatMessage) returns (stream ChatMessage);
}
What is the reason behind this decision, and how a similar domain can be modelled in gRPC?
Simplicity. It is much easier to model a request/response as a single payload rather than varadic, especially in your case, where you want the multiplicity to be different - what, for example, would it mean to take
(A, stream B, C, stream D)
And... if you can take multiple elements, can you return multiple too? Many languages support that concept, after all.
No, it is much easier to receive (as either input it output) either a request or a stream of requests of a single type.
In your scenario, perhaps consider the request type being a thing wrapper over a oneof (discriminated union) of all the actual expected messages, and just have your code enforce that the first one is a "join":
message ChatRequest {
oneof RequestType {
JoinRoomRequest join = 1;
ChatMessage message = 2;
}
}
And take a stream of ChatRequest

Where do the ethers come from when sending ethers with .send() function in ethereum contract

I'm learning ethereum token contract following here. I'm confused by the code below:
function sell(uint amount) returns (uint revenue){
if (balanceOf[msg.sender] < amount ) throw; // checks if the sender has enough to sell
balanceOf[this] += amount; // adds the amount to owner's balance
balanceOf[msg.sender] -= amount; // subtracts the amount from seller's balance
revenue = amount * sellPrice;
if (!msg.sender.send(revenue)) { // sends ether to the seller: it's important
throw; // to do this last to prevent recursion attacks
} else {
Transfer(msg.sender, this, amount); // executes an event reflecting on the change
return revenue; // ends function and returns
}
}
the line msg.sender.send(revenue) means to send ethers to the seller. My question is:
Does the ethers to be sent come from msg.sender or from the token contract?
I think they comes from msg.sender. However the msg.sender is actually in behalf of the seller, right? That makes the seller sends himself ethers. May I know how to understand this. And then how do I make a contract send ethers back to a user account automatically?
Thanks!
I did some tests to figure out this question. I find out that the ethers which are sent to destination address are from the token contract instance address.
I was confused before because I didn't understand how a contract instance gains ethers after being constructed. Now I get to know that the contract instance gains ethers when an account invokes a method marked by keyword payable of the contract. When the invoking happens the ethers are sent to the contract address at the meantime. In the demo token code, it is the method buy() who plays the role to send ethers to the contract address.
I'm new for learning ethereum contract. There probably still are some mistakes about what I realize. Please let me know if there are. Appreciate that!
Thanks!
.send is a function belonging to the address type, where the address on which it's called is the recipient. The ETH being sent comes from the smart contract.
You can also use transfer and call. This article does a good job of explaining the differences.
Examples:
address recipient = 0x0000000000000000000000000000000000000000;
// using transfer
recipient.transfer(revenue);
// using call
recipient.call{value: revenue}("");

Unity Client and Server

In Unity4.
I'm making a network client and server.. Two different unity types.
The client is the actual game, the server is a separate plain server.
I don't quite understand what an RPC is. I understand that it is essentially a function called over the network, but how do I use it?
I have to instantiate the object new prefab.. Whenever I look at a tutorial it tells me to do this: transform.position
What is transform.position, isn't it my position?
How do I connect to the server then have my position updated? How do I get other people's position?
My idea was in the update of NetworkManager I would call an RPC to move the player to new position if it's not the same as the old one?
Network.Instantiate (PlayerController, transform.position, transform.rotation, 0);
transform.position?
PlayerController is the FirstPersonController put into a prefab and renamed..
What do I need to make on the server part of it? The server is basically just a connection between all the clients, do I even need the RPC function on the server?
When someone connects, how do I get it so the server tells everyone that someone connects and how do I send that person who just connected the positions of all the new players?
void Update () {
Transform newPos = Network.player.transform;
if (oldPos != newPos)
networkView.RPC ("UpdatePosition", Network.player,
}
public void OnPlayerConnected(NetworkPlayer player){
Network.Instantiate (PlayerController, transform.position, transform.rotation, 0);
}
public void OnPlayerDisconnected(NetworkPlayer player){
Network.RemoveRPCs (player);
Network.DestroyPlayerObjects (player);
}
That is the client so far.. I need the UpdatePosition to update that single player's position on all screens..

Resources