Exemple #1
0
        //it's trader time
        public void RunThread()
        {
            //this client is added to the barrier
            CHANGE_CLIENT_COUNT(true);
            try
            {
                using (Stream clientStream = theClient.GetStream())
                {
                    StreamWriter writer = new StreamWriter(clientStream);
                    StreamReader reader = new StreamReader(clientStream);

                    JsonSerializerOptions jsonOptions = new JsonSerializerOptions
                    {
                        PropertyNamingPolicy        = JsonNamingPolicy.CamelCase,
                        WriteIndented               = false,
                        PropertyNameCaseInsensitive = true
                    };

                    try
                    {
                        Request theRequest = JsonSerializer.Deserialize <Request>(reader.ReadLine(), jsonOptions);

                        bool connected = false;

                        string responseString = "";

                        if (theRequest.GetCode() == Request.CONNECT_REQUEST)
                        {
                            connected = true;
                            theMarket.AddNewTrader(this);
                            responseString = JsonSerializer.Serialize <ConnectResponse>(new ConnectResponse(true, theMarket.GetMarketInfo(), id), jsonOptions);
                        }
                        else
                        {
                            responseString = JsonSerializer.Serialize <GenericResponse>(new GenericResponse(false), jsonOptions);
                        }
                        writer.WriteLine(responseString);
                        writer.Flush();



                        while (connected)
                        {
                            //true if this client has the stock, false otherwise.
                            bool hasTheStock = theMarket.GetStockholder().Equals(id);

                            bool waitForMarketUpdate = false;

                            try
                            {
                                //read the request
                                theRequest = JsonSerializer.Deserialize <Request>(reader.ReadLine(), jsonOptions);

                                switch (theRequest.code)
                                {
                                case Request.INFO_REQUEST:     //if it's an info request
                                    if (hasTheStock)
                                    {
                                        //if this is the stockholder, get the updated market info, and cancel the CLIENT_BARRIER cancel token
                                        responseString = JsonSerializer.Serialize <GenericResponse>(new GenericResponse(true, theMarket.GetMarketInfo()), jsonOptions);
                                        CANCEL_SOURCE.Cancel();
                                    }
                                    else
                                    {
                                        //if this isn't the stockholder, wait for the market to actually update before responding
                                        waitForMarketUpdate = true;
                                    }
                                    break;

                                case Request.TRADE_REQUEST:     //if it's a trade request
                                                                //go and resolve the trade request (it'll fail if it's a bad request anyway)
                                    responseString = JsonSerializer.Serialize <GiveStockResponse>(theMarket.AttemptToGiveStock(this, theRequest.body), jsonOptions);
                                    if (hasTheStock)
                                    {
                                        //if this user is (or, if the trade request was successful, was) the stockholder, cancel the CLIENT_BARRIER cancel token.
                                        CANCEL_SOURCE.Cancel();
                                    }
                                    break;

                                case Request.DISCONNECT_REQUEST:
                                    connected = false;     //if a disconnect is requested, stop the looping
                                    break;

                                default:
                                    //if the user sent a stupid request (like another connect request, or a completely invalid request), give them a generic 'wtf you trying to do' response.
                                    responseString = JsonSerializer.Serialize <GenericResponse>(new GenericResponse(false, theMarket.GetMarketInfo()), jsonOptions);
                                    break;
                                }

                                if (waitForMarketUpdate) //if it needs to wait for a market update
                                {
                                    try
                                    {
                                        //wait at the CLIENT_BARRIER (until either everything reaches the barrier, CANCEL_SOURCE gets cancelled, or 1 minute passes)
                                        CLIENT_BARRIER.SignalAndWait(TimeSpan.FromMinutes(1), CANCEL_SOURCE.Token);
                                    }
                                    catch (OperationCanceledException e) //if the barrier gets cancelled
                                    {
                                        //reset the CANCEL_SOURCE token
                                        CANCEL_SOURCE = new CancellationTokenSource();
                                    }
                                    //response will be the current market info
                                    responseString = JsonSerializer.Serialize <GenericResponse>(new GenericResponse(true, theMarket.GetMarketInfo()), jsonOptions);
                                }
                                if (connected) //if user still connected (and expecting a response)
                                {
                                    //write the response to the output stream
                                    writer.WriteLine(responseString);
                                    writer.Flush();
                                }
                            }
                            catch (ArgumentNullException e)
                            {
                                logger.LogError(e.ToString()); //uh oh exceptiony
                            }
                            catch (JsonException j)
                            {
                                logger.LogError(j.ToString()); //jason!?!?!?!?!?
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        logger.LogError(e.ToString()); //report any big problems
                    }
                    finally                            //once a user disconnects
                    {
                        //remove that user from the market
                        theMarket.RemoveTrader(this);

                        //give them a disconnect response (no market info because disconnected traders obviously won't need market info any more)
                        writer.WriteLine(
                            JsonSerializer.Serialize <GenericResponse>(new GenericResponse(true), jsonOptions)
                            );
                        writer.Flush();

                        //close the reader and writer streams, as well as theClient socket.
                        writer.Close();
                        reader.Close();
                        theClient.Close();
                    }
                }
            }
            catch (Exception e)
            {
                //logger.LogError($"Looks like {id} went and killed their connection. Oh well.");
            }
            //this client is removed from the barrier
            CHANGE_CLIENT_COUNT(false);
        }