Пример #1
0
 private void addRequestedClientMethodToQueue(ClientMethod method)
 {
     Monitor.Enter(this.pendingMethodCallsLock);
     this.pending_method_calls[method.id] = method;
     Monitor.Exit(this.pendingMethodCallsLock);
     this.setProcessingNeeded(true);
 }
Пример #2
0
        public void run()
        {
            List <UInt32> method_remove_list = new List <UInt32>();

            //start input thread
            this.inputProcessingThread = new Thread(new ThreadStart(this.__processTransportLayerInput));
            this.inputProcessingThread.Start();

            this.outputProcessingThread = new Thread(new ThreadStart(this.__processTransportLayerOutput));
            this.outputProcessingThread.Start();



            while (this.running)
            {
                //this.tl.ProcessInSingle(false);

                //stop processing until sgnal is received
                while (true)
                {
                    if (this.eventDataNeedsToBeProcessed.WaitOne(100) || (!running))
                    {
                        break;
                    }
                }

                //re-check if we are still running (eraly out)
                if (!running)
                {
                    break;
                }

                /*
                 * process  channels (removing + heavy tasks)
                 *
                 */

                //check for closed channels
                Monitor.Enter(this.lockChannels);
                ICollection keys = this.outChannels.Keys;
                foreach (Object key in keys)
                {
                    Channel channel = (Channel)this.outChannels[key];
                    if (channel.shouldBeClosed && !channel.CloseRequestedForRemote)
                    {
                        Console.WriteLine(String.Format("OUT channel {0}, requesting close from server", channel.ID));
                        this.SendControlMessage(Client.CTRL_MSG_FROM_CLIENT_CHANNEL_SHOULD_CLOSE, Struct.packUInt32(channel.ID).ToArray());
                        channel.CloseRequestedForRemote = true;
                    }
                    if (channel.CloseRequestedForLocal)
                    {
                        this.channelsToRemove.Add(channel);
                    }
                    //processing for out channel in else branch
                }
                keys = this.inChannels.Keys;
                foreach (Object key in keys)
                {
                    Channel channel = (Channel)this.inChannels[key];
                    if (channel.shouldBeClosed && !channel.CloseRequestedForRemote)
                    {
                        Console.WriteLine(String.Format("IN channel {0}, requesting close from server", channel.ID));
                        this.SendControlMessage(Client.CTRL_MSG_FROM_CLIENT_CHANNEL_SHOULD_CLOSE, Struct.packUInt32(channel.ID).ToArray());
                        channel.CloseRequestedForRemote = true;
                    }
                    if (channel.CloseRequestedForLocal)
                    {
                        //check if not already in remove list, because handled as outChannel
                        if (!this.channelsToRemove.Contains(channel))
                        {
                            this.channelsToRemove.Add(channel);
                        }
                    }
                    //processing for in channel in else branch
                }

                //remove closed channels
                foreach (Channel channel in this.channelsToRemove)
                {
                    if (this.inChannels.Contains(channel.ID))
                    {
                        this.inChannels.Remove(channel.ID);
                    }
                    if (this.outChannels.Contains(channel.ID))
                    {
                        this.outChannels.Remove(channel.ID);
                    }
                    channel.onClose();
                    Console.WriteLine(String.Format("Channel {0} closed", channel.ID));
                    this.SendControlMessage(Client.CTRL_MSG_FROM_CLIENT_CHANNEL_CLOSED, Struct.packUInt32(channel.ID).ToArray());
                }
                channelsToRemove.Clear();

                //if the channel itself needs processing (not input or output) do it here

                Monitor.Exit(this.lockChannels);

                /*
                 * remove exited processes
                 */
                Monitor.Enter(this.exitedProcessesLock);
                foreach (ClientProcess cproc in this.exitedProcesses)
                {
                    Monitor.Enter(this.pendingClientProcessesLock);
                    this.pending_client_processes.Remove(cproc.Id);
                    cproc.Dispose();
                    Monitor.Exit(this.pendingClientProcessesLock);

                    //ToDo: inform client about process removement
                    this.SendControlMessage(Client.CTRL_MSG_FROM_CLIENT_PROCESS_EXITED, (Struct.packUInt32((UInt32)cproc.Id)).ToArray());

                    //ToDo: destroy channels and inform client
                }
                this.exitedProcesses.Clear();
                Monitor.Exit(this.exitedProcessesLock);

                /*
                 * Process running methods
                 */
                Monitor.Enter(this.pendingMethodCallsLock);

                ICollection method_ids = this.pending_method_calls.Keys;
                foreach (UInt32 method_id in method_ids)
                {
                    if (this.pending_method_calls.ContainsKey(method_id)) //we have to recheck if the method still exists in every iteration
                    {
                        ClientMethod method = (ClientMethod)this.pending_method_calls[method_id];


                        //check if method has been started, do it if not
                        if (!method.started)
                        {
                            //find method implementation
                            MethodInfo method_implementation = this.GetType().GetMethod(method.name, BindingFlags.NonPublic | BindingFlags.Instance);

                            if (method_implementation != null)
                            {
                                try
                                {
                                    byte[] method_result = (byte[])method_implementation.Invoke(this, new Object[] { method.args });
                                    method.setResult(method_result);
                                }
                                catch (ClientMethodException e)
                                {
                                    method.setError(String.Format("Method '{0}' throwed error:\n{1}", method.name, e.Message));
                                }
                                catch (Exception e)
                                {
                                    method.setError(String.Format("'{0}' exception:\n{1}", method.name, e.InnerException.Message));
                                    Console.WriteLine("Catch block of Method invocation");
                                }
                            }
                            else
                            {
                                method.setError(String.Format("Method '{0}' not found!", method.name));
                            }
                        }

                        if (method.finished)
                        {
                            //Enqueue response and remove method from pending ones
                            byte[] response = method.createResponse();
                            this.SendControlMessage(Client.CTRL_MSG_FROM_CLIENT_RUN_METHOD_RESPONSE, response);
                            //this.pending_method_calls.Remove(method_id);

                            //add method to remove list
                            method_remove_list.Add(method_id);
                        }
                    }
                }
                Monitor.Exit(this.pendingMethodCallsLock);

                //remove finished methods
                Monitor.Enter(this.pendingMethodCallsLock);
                foreach (UInt32 method_id in method_remove_list)
                {
                    this.pending_method_calls.Remove(method_id);
                }
                Monitor.Exit(this.pendingMethodCallsLock);
            }
        }
Пример #3
0
        private void __processTransportLayerInput()
        {
            //For now only input of control channel has to be delivered
            // Input for ProcessChannels (STDIN) is directly written to the STDIN pipe of the process (when TransportLayer enqueues data)


            while (this.running)
            {
                this.tl.waitForData();  // blocks if no input from transport layer

                /*
                 * hand over data to respective channels
                 */
                while (this.tl.hasData()) //as long as linklayer has data
                {
                    List <byte> stream = new List <byte>(this.tl.readInputStream());
                    UInt32      ch_id  = Struct.extractUInt32(stream);

                    byte[] data = stream.ToArray(); //the extract method removed the first elements from the List<byte> and we convert back to an array now

                    Channel target_ch = this.GetChannel(ch_id);
                    if (target_ch == null)
                    {
                        Console.WriteLine(String.Format("Received data for channel with ID {0}, this channel doesn't exist!", ch_id));
                        continue;
                    }

                    target_ch.EnqueueInput(data);
                }

                /*
                 * process control channel data
                 */
                while (control_channel.hasPendingInData())
                {
                    List <byte> data = Struct.packByteArray(control_channel.read());

                    // extract control message type
                    UInt32 CtrlMessageType = Struct.extractUInt32(data);

                    switch (CtrlMessageType)
                    {
                    case CTRL_MSG_FROM_SERVER_RUN_METHOD:
                        ClientMethod new_method = new ClientMethod(data);
                        this.addRequestedClientMethodToQueue(new_method);

                        Console.WriteLine(String.Format("Received control message RUN_METHOD! Method ID: {0}, Method Name: {1}, Method Args: {2}", new_method.id, new_method.name, new_method.args));
                        break;

                    case CTRL_MSG_FROM_SERVER_DESTROY:
                        this.SendControlMessage(Client.CTRL_MSG_FROM_CLIENT_DESTROY_RESPONSE);
                        this.stop();
                        break;

                    case CTRL_MSG_FROM_SERVER_CLOSE_CHANNEL:
                        UInt32  channel_id = Struct.extractUInt32(data);
                        Channel ch         = this.GetChannel(channel_id);
                        if (ch != null)
                        {
                            ch.CloseRequestedForLocal = true;
                        }
                        break;

                    default:
                        String data_utf8 = Encoding.UTF8.GetString(data.ToArray());
                        Console.WriteLine(String.Format("Received unknown MESSAGE TYPE for control channel! MessageType: {0}, Data: {1}", CtrlMessageType, data_utf8));
                        break;
                    }
                }
            }
        }