tags:

views:

287

answers:

1

I'm trying to send commands to the Tor control port programmatically to make it refresh the chain. I haven't been able to find any examples in C#, and my solution's not working. The request times out. I have the service running, and I can see it listening on the control port.

public string Refresh()
{
    TcpClient client = new TcpClient("localhost", 9051);
    string response = string.Empty;
    string authenticate = MakeTcpRequest("AUTHENTICATE\r\n", client);
    if (authenticate.Equals("250"))
        response = MakeTcpRequest("SIGNAL NEWNYM\r\n", client);
    client.Close();
    return response;
}

public string MakeTcpRequest(string message, TcpClient client)
{
    client.ReceiveTimeout = 20000;
    client.SendTimeout = 20000;
    string proxyResponse = string.Empty;

    try
    {
        // Send message
        StreamWriter streamWriter = new StreamWriter(client.GetStream());
        streamWriter.Write(message);
        streamWriter.Flush();

        // Read response
        StreamReader streamReader = new StreamReader(client.GetStream());
        proxyResponse = streamReader.ReadToEnd();
    }
    catch (Exception ex)
    {
        // Ignore
    }

    return proxyResponse;
}

Can anyone spot what I'm doing wrong?

EDIT:

Following Hans's suggestion, which he has now deleted for some reason, I tried to send "AUTHENTICATE\n" instead of just "AUTHENTICATE". Now I'm getting back an error from Tor: "551 Invalid quoted string. You need to put the password in double quotes." At least there's some progress.

I then tried to send "AUTHENTICATE \"\"\n", like it wants to, but it times out while waiting for a response.

EDIT:

The command works fine in the Windows Telnet client. I don't even have to add the quotes. Can't figure out what's wrong. Maybe the double quotes aren't encoded correctly when they're sent?

EDIT:

Found the problem. When I send the AUTHENTICATE command, the StreamReader is reading the response to the end, but there is no end because on success the stream is kept open. So I will change it to only read the first line of the response in this case.

public static string MakeTcpRequest(string message, TcpClient client, bool readToEnd)
{
    client.ReceiveTimeout = 20000;
    client.SendTimeout = 20000;
    string proxyResponse = string.Empty;

    try
    {
        // Send message
        StreamWriter streamWriter = new StreamWriter(client.GetStream());
        streamWriter.Write(message);
        streamWriter.Flush();

        // Read response
        StreamReader streamReader = new StreamReader(client.GetStream());
        if (readToEnd)
            proxyResponse = streamReader.ReadToEnd();
        else
            proxyResponse = streamReader.ReadLine();
    }
    catch (Exception ex)
    {
        throw ex;
    }

    return proxyResponse;
}
A: 

Found a solution on my own. Edited the first post.

Ed