SecondBot/CLI/HttpServer/http_server.cs
2020-05-03 23:45:16 +01:00

210 lines
7.9 KiB
C#

using BetterSecondBotShared.IO;
using BetterSecondBotShared.Json;
using BetterSecondBotShared.logs;
using BetterSecondBotShared.Static;
using BSB;
using BSB.bottypes;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace BetterSecondBot.HttpServer
{
public class http_server
{
protected HttpListener listener;
protected SecondBot Bot;
public SecondBot GetBot { get { return Bot; } }
protected JsonConfig Config;
public JsonConfig GetConfig { get { return Config; } }
protected HTTPCommandsInterfaceGet get_controler;
protected HTTPCommandsInterfacePost post_controler;
protected string url = "";
protected bool require_signed_commands;
public bool ShutdownHTTP { get; set; }
public bool HTTPCnCmode { get; set; }
public string GetStatus()
{
string reply = "";
if(Bot == null)
{
reply += "- No bot";
}
else
{
Bot.LastStatusMessage = Bot.GetStatus();
reply += Bot.LastStatusMessage;
}
if(listener == null)
{
reply += " - No HTTP listener";
}
return reply;
}
public void NewBot()
{
Bot = new SecondBot();
}
public void KillBot()
{
Bot.GetClient.Network.Logout();
Bot.GetClient.Network.Shutdown(OpenMetaverse.NetworkManager.DisconnectType.ClientInitiated);
Bot = null;
}
public void start_http_server(JsonConfig setConfig)
{
start_http_server(setConfig, null);
}
public void start_http_server(SecondBot LinkBot, JsonConfig setConfig)
{
start_http_server(setConfig, LinkBot);
}
protected void start_http_server(JsonConfig setConfig, SecondBot LinkBot)
{
Config = setConfig;
require_signed_commands = Config.HttpRequireSigned;
Bot = LinkBot;
int port = Math.Abs(Config.Httpport);
if (Config.Httpkey.Length < 12)
{
Config.Httpkey = helpers.GetSHA1("" + helpers.UnixTimeNow().ToString() + "" + new Random().Next(4, 9999).ToString()).Substring(0, 12);
}
if (Config.HttpHost == "docker")
{
url = "http://*:" + port.ToString() + "/";
}
else
{
if (url.StartsWith("http://") == false)
{
url = "http://localhost:" + port.ToString() + "";
}
if (url.EndsWith("/") == false)
{
url = "" + url + "/";
}
}
open_http_service();
}
protected async Task HandleIncomingConnections()
{
while(Bot.KillMe == false)
{
HttpListenerContext ctx = await listener.GetContextAsync();
HttpListenerRequest req = ctx.Request;
HttpListenerResponse resp = ctx.Response;
string test = req.Url.AbsolutePath.Substring(1);
test = test.Replace(Config.HttpPublicUrlBase, "");
List<string> http_args = test.Split('/', StringSplitOptions.RemoveEmptyEntries).ToList();
byte[] data = Encoding.UTF8.GetBytes("totaly fucked");
resp.StatusCode = 404;
if (req.HttpMethod == "GET")
{
resp.StatusCode = 200;
string command = "status";
if (http_args.Count > 0)
{
command = http_args.Last();
}
string content = String.Join("{@}", get_controler.Call(command, ""));
data = Encoding.UTF8.GetBytes(content);
}
else if (req.HttpMethod == "POST")
{
string text;
using (var reader = new StreamReader(req.InputStream,req.ContentEncoding))
{
text = reader.ReadToEnd();
}
//"command = logout & args = &passkey = Kp83VZaEhcy"
string[] pairs = text.Split('&', StringSplitOptions.RemoveEmptyEntries);
Dictionary<string, string> post_args = new Dictionary<string, string>();
foreach(string B in pairs)
{
string[] bits = B.Split('=', StringSplitOptions.RemoveEmptyEntries);
if (bits.Length == 2)
{
post_args.Add(bits[0].Trim(), bits[1].Trim());
}
}
if (post_args.ContainsKey("command") == true)
{
if (post_args.ContainsKey("passkey") == true)
{
if (Config.Httpkey == post_args["passkey"])
{
string command = post_args["command"];
resp.StatusCode = 200;
string arg = "";
if (post_args.ContainsKey("args") == true)
{
arg = post_args["args"];
}
data = Encoding.UTF8.GetBytes(String.Join("###", post_controler.Call(command, arg)));
}
else
{
data = Encoding.UTF8.GetBytes("totaly fucked");
}
}
else
{
data = Encoding.UTF8.GetBytes("post request missing command");
}
}
else
{
data = Encoding.UTF8.GetBytes("post request missing command");
}
}
resp.ContentType = "text/html";
resp.ContentEncoding = Encoding.UTF8;
resp.ContentLength64 = data.LongLength;
await resp.OutputStream.WriteAsync(data, 0, data.Length);
resp.Close();
}
}
protected void open_http_service()
{
get_controler = new HTTPCommandsInterfaceGet(Bot,this);
post_controler = new HTTPCommandsInterfacePost(Bot,this);
Thread t = new Thread(delegate (object _)
{
bool ok = true;
try
{
listener = new HttpListener();
listener.Prefixes.Add(url);
listener.Start();
}
catch (Exception e)
{
ok = false;
ConsoleLog.Crit("Unable to setup http service: "+e.Message+"");
ConsoleLog.Crit("if running on windows please check: https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/configuring-http-and-https?redirectedfrom=MSDN");
}
if (ok == true)
{
ConsoleLog.Status("Listening for connections on " + url + "");
Task listenTask = HandleIncomingConnections();
listenTask.GetAwaiter().GetResult();
}
listener.Close();
})
{
Name = "http thead",
IsBackground = true
};
t.Start();
}
}
}