Ejemplo n.º 1
0
        static async Task <GeminiResponse> ReadMessage(SslStream sslStream)
        {
            // Read the  message sent by the server.
            // The end of the message is signaled using the
            // "<EOF>" marker.
            byte[] buffer = new byte[2048];
            int    bytes  = -1;

            bytes = await sslStream.ReadAsync(buffer, 0, buffer.Length);

            GeminiResponse resp = new GeminiResponse(buffer.ToList(), bytes);

            while (bytes != 0)
            {
                bytes = await sslStream.ReadAsync(buffer, 0, buffer.Length);

                resp.pyld.AddRange(buffer.Take(bytes));
            }

            return(resp);
        }
Ejemplo n.º 2
0
        public async static Task <IResponse> Fetch(Uri hostURL)
        {
            int refetchCount = 0;

Refetch:
            // Stop unbounded redirects
            if (refetchCount >= 5)
            {
                return(new GeminiResponse {
                    codeMajor = '3',
                    codeMinor = '9',
                    meta = "",
                    pyld = Encoding.UTF8.GetBytes("Too many redirects!").ToList(),
                    mime = "text/plain",
                    encoding = "UTF-8"
                });
            }
            refetchCount += 1;

            // Set remote port
            int port = hostURL.Port;

            if (port == -1)
            {
                port = DefaultPort;
            }

            // Create a TCP/IP client socket.
            // machineName is the host running the server application.
            TcpClient client;

            try {
                client = new TcpClient(hostURL.Host, port);
            } catch (Exception e) {
                Log.Error(e, "Connection failure");
                throw e;
            }

            // Create an SSL stream that will close the client's stream.
            SslStream sslStream = new SslStream(
                client.GetStream(),
                false,
                new RemoteCertificateValidationCallback(ValidateServerCertificate),
                null
                );

            // The server name must match the name on the server certificate.
            try {
                await sslStream.AuthenticateAsClientAsync(hostURL.Host);
            } catch (AuthenticationException e) {
                Log.Error(e, "Authentication failure");
                client.Close();
                throw e;
            }

            // Gemini request format: URI\r\n
            byte[] messsage = Encoding.UTF8.GetBytes(hostURL.ToString() + "\r\n");
            await sslStream.WriteAsync(messsage, 0, messsage.Count());

            await sslStream.FlushAsync();

            // Read message from the server.
            GeminiResponse resp = await ReadMessage(sslStream);

            // Close the client connection.
            client.Close();

            // Determine what to do w/ that
            switch (resp.codeMajor)
            {
            //case '1': // Text input
            // TODO
            //break;
            case '2':     // OK
                break;

            case '3':     // Redirect
                hostURL = new Uri(resp.meta);
                goto Refetch;

            case '4':     // Temporary failure
            case '5':     // Permanent failure
            case '6':     // Client cert required
                Log.Error(resp.ToString());
                resp.pyld = Encoding.UTF8.GetBytes(resp.ToString()).ToList();
                break;

            default:
                throw new Exception(
                          string.Format("Invalid response code {0}", resp.codeMajor)
                          );
            }

            return(resp);
        }