Example #1
0
 public NpcBlockingThreadHander(String clientString, INpcServerCallback callback, Socket socket,
                                NpcExecutor npcExecutor, INpcHtmlGenerator npcHtmlGenerator)
     : base(clientString, callback, npcExecutor, npcHtmlGenerator)
 {
     this.socket           = socket;
     this.socketLineReader = new SocketLineReader(socket, Encoding.ASCII, Buf.DefaultInitialCapacity, Buf.DefaultExpandLength);
 }
Example #2
0
        public void Dispose()
        {
            SocketLineReader cachedSocketLineReader = this.socketLineReader;

            this.socketLineReader = null;
            if (cachedSocketLineReader != null)
            {
                cachedSocketLineReader.Dispose();
            }
        }
Example #3
0
        public NpcClient(EndPoint serverEndPoint, RemoteNpcInterface[] expectedInterfaces, Boolean threadSafe)
        {
            this.serverEndPoint     = serverEndPoint;
            this.expectedInterfaces = expectedInterfaces;
            this.threadSafe         = threadSafe;
            this.socketLineReader   = null;

            this.enumAndObjectTypes = new List <Type>();
            InitializeStaticClientTypeFinder();
        }
Example #4
0
        public NpcClient(Socket socket, RemoteNpcInterface[] expectedInterfaces, Boolean threadSafe)
        {
            this.serverEndPoint     = socket.RemoteEndPoint;
            this.expectedInterfaces = expectedInterfaces;
            this.threadSafe         = threadSafe;

            this.socketLineReader = (socket == null || !socket.Connected) ? null :
                                    new SocketLineReader(socket, Encoding.ASCII, Buf.DefaultInitialCapacity, Buf.DefaultExpandLength);

            this.enumAndObjectTypes = new List <Type>();
            InitializeStaticClientTypeFinder();
        }
Example #5
0
        void Connect()
        {
            if (socketLineReader == null || socketLineReader.socket == null || !socketLineReader.socket.Connected)
            {
                if (socketLineReader != null)
                {
                    socketLineReader.Dispose();
                }

                socketLineReader = new SocketLineReader(new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
                                                        Encoding.ASCII, Buf.DefaultInitialCapacity, Buf.DefaultExpandLength);
                socketLineReader.socket.Connect(serverEndPoint);
            }
        }
Example #6
0
        public static List <RemoteNpcObject> GetServerInterface(SocketLineReader socketLineReader,
                                                                out Dictionary <String, RemoteNpcInterface> serverInterfaces)
        {
            socketLineReader.socket.Send(Encoding.ASCII.GetBytes(":interface\n"));

            serverInterfaces = new Dictionary <String, RemoteNpcInterface>();
            List <SosMethodDefinition> methodDefinitionList = new List <SosMethodDefinition>();

            while (true)
            {
                String interfaceName = socketLineReader.ReadLine();
                if (interfaceName == null)
                {
                    throw UnexpectedClose(socketLineReader);
                }
                if (interfaceName.Length <= 0)
                {
                    break;
                }

                // Get parent interfaces
                String[] parentInterfaceNames = null;
                Int32    spaceIndex           = interfaceName.IndexOf(' ');
                if (spaceIndex >= 0)
                {
                    parentInterfaceNames = interfaceName.Substring(spaceIndex + 1).Split(' ');
                    interfaceName        = interfaceName.Remove(spaceIndex);
                }

                while (true)
                {
                    String methodDefinitionLine = socketLineReader.ReadLine();
                    if (methodDefinitionLine == null)
                    {
                        throw UnexpectedClose(socketLineReader);
                    }
                    if (methodDefinitionLine.Length <= 0)
                    {
                        break;
                    }

                    SosMethodDefinition methodDefinition = SosTypes.ParseMethodDefinition(methodDefinitionLine, 0);
                    methodDefinitionList.Add(methodDefinition);
                }
                serverInterfaces.Add(interfaceName, new RemoteNpcInterface(interfaceName, parentInterfaceNames, methodDefinitionList.ToArray()));
                methodDefinitionList.Clear();
            }

            List <RemoteNpcObject> serverObjects = new List <RemoteNpcObject>();

            while (true)
            {
                String objectLine = socketLineReader.ReadLine();
                if (objectLine == null)
                {
                    throw UnexpectedClose(socketLineReader);
                }
                if (objectLine.Length <= 0)
                {
                    break;
                }

                String               objectName     = objectLine.Peel(out objectLine);
                String[]             interfaceNames = objectLine.Split(RemoteNpcObject.SplitChars, StringSplitOptions.RemoveEmptyEntries);
                RemoteNpcInterface[] interfaces     = new RemoteNpcInterface[interfaceNames.Length];
                for (int i = 0; i < interfaceNames.Length; i++)
                {
                    String             interfaceName = interfaceNames[i];
                    RemoteNpcInterface npcInterface;
                    if (!serverInterfaces.TryGetValue(interfaceName, out npcInterface))
                    {
                        throw new FormatException(String.Format("The NPC server returned interface '{0}' in the :objects command but not in the :interfaces command",
                                                                interfaceName));
                    }
                    interfaces[i] = npcInterface;
                }
                serverObjects.Add(new RemoteNpcObject(objectName, interfaces));
            }

            return(serverObjects);
        }
Example #7
0
        // expectedReturnType can be null, but providing the expected return type makes it unnecessary to search
        // each assembly for the type
        Object PerformCall(Type expectedReturnType, String methodName, String rawNpcLine)
        {
            if (threadSafe)
            {
                Monitor.Enter(serverEndPoint);
            }
            try
            {
                //
                // The reason for the retry logic is because if the underlying socket is disconnected, it may not
                // fail until after a send and a receive...so the socket should be reconnected and the request should
                // be repeated only once.
                //
                for (UInt32 attempt = 0; ; attempt++)
                {
                    try
                    {
                        Connect();

                        socketLineReader.socket.Send(Encoding.UTF8.GetBytes(rawNpcLine.ToString()));

                        String returnLineString = socketLineReader.ReadLine();
                        if (returnLineString == null)
                        {
                            if (attempt == 0)
                            {
                                Dispose();
                                continue; // Retry
                            }
                            throw UnexpectedClose();
                        }

                        NpcReturnLine returnLine = new NpcReturnLine(returnLineString);

                        if (returnLine.exceptionMessage != null)
                        {
                            ThrowExceptionFromCall(methodName, returnLine);
                        }

                        if (expectedReturnType == null)
                        {
                            if (returnLine.sosTypeName.Equals("Void"))
                            {
                                return(null);
                            }
                            expectedReturnType = GetTypeFromSosTypeName(returnLine.sosTypeName);
                        }
                        else
                        {
                            if (!returnLine.sosTypeName.Equals(expectedReturnType.SosTypeName()))
                            {
                                throw new InvalidOperationException(String.Format("Expected return type to be {0} but was {1}",
                                                                                  expectedReturnType.SosTypeName(), returnLine.sosTypeName));
                            }
                        }

                        if (expectedReturnType == typeof(void))
                        {
                            return(null);
                        }

                        Object returnObject;
                        Int32  valueStringOffset = Sos.Deserialize(out returnObject, expectedReturnType,
                                                                   returnLine.sosSerializationString, 0, returnLine.sosSerializationString.Length);

                        if (valueStringOffset != returnLine.sosSerializationString.Length)
                        {
                            throw new InvalidOperationException(String.Format(
                                                                    "Used {0} characters to deserialize object of type '{1}' but the serialization string had {2} characters",
                                                                    valueStringOffset, expectedReturnType.SosTypeName(), returnLine.sosSerializationString.Length));
                        }

                        return(returnObject);
                    }
                    catch (SocketException)
                    {
                        if (socketLineReader != null)
                        {
                            socketLineReader.Dispose();
                            socketLineReader = null;
                        }
                        if (attempt == 0)
                        {
                            continue; // Retry
                        }
                        throw;
                    }
                }
            }
            finally
            {
                if (threadSafe)
                {
                    Monitor.Exit(serverEndPoint);
                }
            }
        }
Example #8
0
        public void UpdateAndVerifyEnumAndObjectTypes(NpcVerifyCriteria criteria)
        {
            if (threadSafe)
            {
                Monitor.Enter(serverEndPoint);
            }
            try
            {
                //
                // The reason for the retry logic is because if the underlying socket is disconnected, it may not
                // fail until after a send and a receive...so the socket should be reconnected and the request should
                // be repeated only once.
                //
                for (UInt32 attempt = 0; ; attempt++)
                {
                    try
                    {
                        Connect();
                        socketLineReader.socket.Send(Encoding.UTF8.GetBytes(":type\n"));

                        enumAndObjectTypes.Clear();

                        while (true)
                        {
                            String typeDefinitionLine = socketLineReader.ReadLine();
                            if (typeDefinitionLine == null)
                            {
                                if (attempt == 0)
                                {
                                    Dispose();
                                    continue; // Retry
                                }
                                throw UnexpectedClose();
                            }
                            if (typeDefinitionLine.Length == 0)
                            {
                                break;                                 // empty line
                            }
                            Int32  spaceIndex     = typeDefinitionLine.IndexOf(' ');
                            String sosTypeName    = typeDefinitionLine.Remove(spaceIndex);
                            String typeDefinition = typeDefinitionLine.Substring(spaceIndex + 1);

                            Type type = GetTypeFromSosTypeName(sosTypeName);
                            if (typeDefinition.StartsWith("Enum"))
                            {
                                SosEnumDefinition enumDefinition = SosTypes.ParseSosEnumTypeDefinition(typeDefinition, 4);
                                enumDefinition.VerifyType(type, (SosVerifyCriteria)criteria);
                            }
                            else
                            {
                                SosObjectDefinition objectDefinition = SosTypes.ParseSosObjectTypeDefinition(typeDefinition, 0);
                                objectDefinition.VerifyType(type);
                            }
                            enumAndObjectTypes.Add(type);
                        }
                        return;
                    }
                    catch (SocketException)
                    {
                        if (socketLineReader != null)
                        {
                            socketLineReader.Dispose();
                            socketLineReader = null;
                        }
                        if (attempt == 0)
                        {
                            continue; // Retry
                        }
                        throw;
                    }
                }
            }
            finally
            {
                if (threadSafe)
                {
                    Monitor.Exit(serverEndPoint);
                }
            }
        }
Example #9
0
        //
        // Methods Definitions
        // If the interface is updated and expectedInterfaces is not null, then the interfaces will be checked.
        public List <RemoteNpcObject> GetServerInterface(Boolean forceUpdateFromServer)
        {
            if (threadSafe)
            {
                Monitor.Enter(serverEndPoint);
            }
            try
            {
                if (cachedServerInterfaces == null || forceUpdateFromServer)
                {
                    //
                    // The reason for the retry logic is because if the underlying socket is disconnected, it may not
                    // fail until after a send and a receive...so the socket should be reconnected and the request should
                    // be repeated only once.
                    //
                    Boolean retryOnSocketException = true;
RETRY_LOCATION:
                    try
                    {
                        Connect();

                        cachedServerObjects = GetServerInterface(socketLineReader, out cachedServerInterfaces);

                        if (expectedInterfaces != null)
                        {
                            String serverInterfaceDiff = ServerInterfaceMethodsDiff(cachedServerInterfaces, expectedInterfaces);
                            if (serverInterfaceDiff != null)
                            {
                                throw new NpcInterfaceMismatch(serverInterfaceDiff);
                            }
                        }
                    }
                    catch (SocketException)
                    {
                        if (socketLineReader != null)
                        {
                            socketLineReader.Dispose();
                            socketLineReader = null;
                        }
                        if (retryOnSocketException)
                        {
                            retryOnSocketException = false;
                            goto RETRY_LOCATION;
                        }
                        throw;
                    }
                }
                return(cachedServerObjects);
            }
            catch (Exception)
            {
                cachedServerInterfaces = null;
                cachedServerObjects    = null;
                throw;
            }
            finally
            {
                if (threadSafe)
                {
                    Monitor.Exit(serverEndPoint);
                }
            }
        }
Example #10
0
 static InvalidOperationException UnexpectedClose(SocketLineReader socketLineReader)
 {
     socketLineReader.Dispose();
     return(new InvalidOperationException("Server closed unexpectedly"));
 }