Completely overhaul connection and session system.

This commit is contained in:
Wirlaburla 2023-09-23 11:19:26 -05:00
parent 4e7f8a85f8
commit 53e19a604f
4 changed files with 237 additions and 80 deletions

View File

@ -1,29 +1,39 @@
#ifndef H_CLIENT
#define H_CLIENT
#include <vector>
#include <thread>
#include "drone.h"
#define SERVERADDR "209.240.84.122"
#define AUTOSERVER 6650
#define ROOMSERVER 5672
// This should be your MTU, but I don't have a method for auto-detecting that.
#define BUFFERSIZE 1440
#define BUFFERSIZE 65535
bool netstatus = false;
WINDOW* wlog;
WINDOW* wform;
FORM *form;
FIELD *entries[1];
char* protocol = "24";
int autosock;
int roomsock;
std::thread aRecv_t;
std::thread rRecv_t;
std::thread rKA_t;
char* worldsserver = "209.240.84.122";
uint16_t autoport = 6650;
uint16_t roomport = 5672;
int protocol = 24;
char* version = "0000000000";
char* default_avatar = "avatar:pengo.mov";
char* avatars = "1024";
char* avatar = "avatar:pengo.mov";
int avatars = 253;
char* room = "GroundZero#Reception";
char* dimension = "dimension-1";
uint16_t roomID = 1;
char login_username[128];
char login_password[128];
char login_username[16];
char login_password[16];
uint16_t xPos = 0;
uint16_t yPos = 0;
@ -40,12 +50,14 @@ std::vector<char*> mutes;
static char* trim(char *str);
char* zero(int size);
unsigned char* uzero(int size);
void autoInit(int sock_fd);
void roomInit(int sock_fd);
void reciever(int sock_fd);
void autoInit();
void roomInit();
void roomKeepAlive();
void reciever(int sock_fd, bool autoserver);
void sessInit(int sock_fd, char* username, char* password);
void sessExit(int sock_fd);
void readPropertyList(unsigned char* in);
std::map<char, char*> readOldPropertyList(unsigned char* in);
void setAvatar(int sock_fd, char* avatar);
void roomIDReq(int sock_fd, char* room);
void teleport(int sock_fd, int x, int y, int z, int rot);

View File

@ -1,9 +1,9 @@
#include <map>
#include <thread>
#include <chrono>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <memory>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
@ -16,6 +16,7 @@
#include "client.h"
#include "var_error.h"
#include "cmds.h"
#include "props.h"
static char* trim(char *str) {
char *end;
@ -29,29 +30,27 @@ static char* trim(char *str) {
*(end+1) = '\0';
return str;
}
struct sockaddr_in auto_addr;
struct sockaddr_in room_addr;
int main(int argc, char const* argv[]) {
unsigned char bufout[BUFFERSIZE] = {0};
int status, valread, autosock, roomsock;
struct sockaddr_in serv_addr;
std::cout << "Username: "; std::cin >> login_username;
auto_addr.sin_family = AF_INET;
inet_pton(AF_INET, worldsserver, &auto_addr.sin_addr);
auto_addr.sin_port = htons(autoport);
room_addr.sin_family = AF_INET;
inet_pton(AF_INET, worldsserver, &room_addr.sin_addr);
room_addr.sin_port = htons(roomport);
initscr();
cbreak();
noecho();
refresh();
printf("*Password: ");
std::cin >> login_password;
wlog = newwin(LINES-1, COLS, 0, 0);
wmove(wlog, LINES-2, 0);
scrollok(wlog, true);
wprintw(wlog, "\n*Connecting to Worlds.com. Enter '.help' for a list of commands.");
wform = newwin(1, COLS, LINES-1, 0);
wmove(wform, 0, 0);
scrollok(wform, true);
keypad(wform, TRUE);
@ -63,33 +62,17 @@ int main(int argc, char const* argv[]) {
form = new_form(entries);
set_form_win(form, wform);
post_form(form);
set_current_field(form, entries[0]);
if ((autosock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
perror("Socket creation error.");
serv_addr.sin_family = AF_INET;
inet_pton(AF_INET, SERVERADDR, &serv_addr.sin_addr);
serv_addr.sin_port = htons(AUTOSERVER);
if ((status = connect(autosock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))) < 0)
perror("AutoServ connection failed.");
// Initialize connection.
std::thread aRecv_t(reciever, autosock);
autoInit(autosock);
serv_addr.sin_port = htons(ROOMSERVER);
close(autosock);
if ((roomsock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
perror("Socket creation error.");
if ((status = connect(roomsock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))) < 0)
perror("RoomServ connection failed");
std::thread rRecv_t(reciever, roomsock);
std::thread rInit_t(roomInit, roomsock);
pos_form_cursor(form);
wmove(wform, 0, 0);
wrefresh(wform);
wmove(wlog, LINES-2, 0);
wrefresh(wlog);
refresh();
wprintw(wlog, "\n*Welcome to WorldsTerm. Enter '.help' for a list of commands.");
wprintw(wlog, "\n*To get started, '.connect' to the server and '.login'.");
wrefresh(wlog);
int key = 0;
while ((key = wgetch(wform))) {
@ -97,6 +80,7 @@ int main(int argc, char const* argv[]) {
if (key == 10) {
form_driver(form, REQ_VALIDATION);
char* inmsg = trim(field_buffer(entries[0], 0));
set_field_buffer(entries[0], 0, "");
int msglen = 0;
if ((msglen = strlen(inmsg)) > 0) {
if (inmsg[0] == '.' && msglen > 1) { // Starting a command.
@ -139,6 +123,34 @@ int main(int argc, char const* argv[]) {
inmsg = new char[256];
srcLine = 0;
}
} else if (strcmp(cmd, "connect") == 0) {
autoInit();
} else if (strcmp(cmd, "disconnect") == 0) {
if (aRecv_t.joinable()) aRecv_t.detach();
wsend(autosock, new unsigned char[] {0x03, 0x01, CMD_SESSEXIT}, 0);
} else if (strcmp(cmd, "login") == 0) {
char username[16] = {0}; j = 0;
while (msgoff < msglen && (s = inmsg[msgoff++]) != 0x20) {
username[j++] = s;
}
username[j++] = 0;
char password[16] = {0}; j = 0;
while (msgoff < msglen && (s = inmsg[msgoff++]) != 0x00) {
password[j++] = s;
}
password[j++] = 0;
if (strlen(username) == 0 || strlen(password) == 0) { wprintw(wlog, "\n*.login <username> <password>"); continue; }
int u = 0;
for(u; u < strlen(username); u++)
login_username[u] = username[u];
login_username[u];
int p = 0;
for(p; p < strlen(password); p++)
login_password[p] = password[p];
login_password[p];
wprintw(wlog, "\n*Logging in as %s.", username);
sessInit(autosock, username, password);
} else if ((strcmp(cmd, "w") == 0 || strcmp(cmd, "whisper") == 0) && srcLine < 0) {
int k = 1;
bufout[k++] = 0;
@ -368,6 +380,9 @@ int main(int argc, char const* argv[]) {
wprintw(wlog, "%s %s", _f?",":"", value.name);
_f=true;
}
} else if (strcmp(cmd, "logout") == 0) {
wsend(autosock, new unsigned char[] {0x03, 0x01, CMD_SESSEXIT}, 0);
wsend(roomsock, new unsigned char[] {0x03, 0x01, CMD_SESSEXIT}, 0);
} else if (strcmp(cmd, "q") == 0) {
goto quit;
} else {
@ -396,7 +411,6 @@ int main(int argc, char const* argv[]) {
wsend(roomsock, bufout, 0);
}
bufout[0] = 0;
set_field_buffer(entries[0], 0, "");
}
} else if (key == KEY_LEFT) {
form_driver(form, REQ_PREV_CHAR);
@ -427,32 +441,44 @@ int main(int argc, char const* argv[]) {
return 0;
}
void autoInit(int sock_fd) {
wsend(sock_fd, new unsigned char[] {0x03, 0xff, CMD_PROPREQ}, 0);
sleep(1);
sessInit(sock_fd, login_username, login_password);
sleep(1);
setAvatar(sock_fd, default_avatar);
roomIDReq(sock_fd, room);
void autoInit() {
if ((autosock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
perror("AutoSock creation error");
pos_form_cursor(form);
wrefresh(wform);
wrefresh(wlog);
refresh();
if (connect(autosock, (struct sockaddr*)&auto_addr, sizeof(auto_addr)) < 0)
perror("AutoServ connection failed");
wprintw(wlog, "\n*Connected to AutoServer %s:%i", worldsserver, autoport);
// Initialize connection.
aRecv_t = std::thread(reciever, autosock, true);
wsend(autosock, new unsigned char[] {0x03, 0xff, CMD_PROPREQ}, 0);
wrefresh(wlog);
netstatus = true;
}
void roomInit(int sock_fd) {
wsend(sock_fd, new unsigned char[] {0x03, 0xff, CMD_PROPREQ}, 0);
sleep(1);
sessInit(sock_fd, login_username, login_password);
setAvatar(sock_fd, default_avatar);
while (true) {
teleport(sock_fd, xPos, yPos, zPos, rot);
sleep(15);
void roomInit() {
if ((roomsock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
perror("AutoSock creation error");
if ((connect(roomsock, (struct sockaddr*)&room_addr, sizeof(room_addr))) < 0)
perror("RoomServ connection failed");
wprintw(wlog, "\n*Connected to RoomServer %s:%i", worldsserver, roomport);
rRecv_t = std::thread(reciever, roomsock, false);
rKA_t = std::thread(roomKeepAlive);
sessInit(roomsock, login_username, login_password);
login_password[0] = 0;
wrefresh(wlog);
}
void roomKeepAlive() {
while (netstatus) {
teleport(roomsock, xPos, yPos, zPos, rot);
sleep(5);
}
}
void reciever(int sock_fd) {
void reciever(int sock_fd, bool autoserver = false) {
unsigned char bufin[BUFFERSIZE] = {};
unsigned char bufout[BUFFERSIZE] = {};
while (read(sock_fd, bufin, sizeof(bufin)) > 0) {
@ -524,7 +550,73 @@ void reciever(int sock_fd) {
objects[shortID] = newDrone;
}
} else if (bufin[p+2] == CMD_SESSEXIT && bufin[p+1] == 0x01) {
close(sock_fd);
if (autoserver) {
wprintw(wlog, "\n*Logged out of %s.", login_username);
login_username[0] = 0;
// Clear
properties.erase(properties.begin(), properties.end());
objects.erase(objects.begin(), objects.end());
rooms.erase(rooms.begin(), rooms.end());
friends.clear();
mutes.clear();
aRecv_t.detach();
netstatus = false;
wprintw(wlog, "\n*Disconnected!", sock_fd);
} else {
wprintw(wlog, "\n*Leaving room %s<%s>", room, dimension);
roomID = 1;
room = "GroundZero#Reception";
dimension = "dimension-1";
xPos = 0;
yPos = 0;
zPos = 0;
rot = 0;
rRecv_t.detach();
rKA_t.detach();
}
} else if (bufin[p+2] == CMD_SESSINIT && bufin[p+1] == 0x01) {
std::map<char, char*> props = readOldPropertyList(&bufin[p]);
int err = VAR_FATAL;
for (const auto& [key, value] : props) {
switch (key) {
case PROP_ERROR:
err = atoi(value);
break;
}
}
if (err != VAR_OK) {
char* errMsg = "UNKNOWN";
switch(err) {
case VAR_BAD_PASSWORD:
errMsg = "Invalid Password."; break;
case VAR_BAD_ACCOUNT:
errMsg = "Account is no longer valid."; break;
case VAR_BAD_IPADDRESS:
errMsg = "Invalid client IP address!"; break;
case VAR_NO_SUCH_USER:
errMsg = "User does not exist."; break;
}
wprintw(wlog, "\n*Error %i: %s", err, errMsg);
if (autoserver) {
aRecv_t.detach();
netstatus = false;
} else {
rRecv_t.detach();
rKA_t.detach();
}
} else {
if (!autoserver) {
memset(&(login_password[0]), 0, sizeof(login_password));
setAvatar(sock_fd, avatar);
} else {
roomIDReq(sock_fd, room);
}
}
} else if ((bufin[p+2] == CMD_ROOMID || bufin[p+2] == 0x1A) && bufin[p+1] == 0x01) {
char *longID = new char[255];
int shortID;
@ -536,6 +628,7 @@ void reciever(int sock_fd) {
shortID = ((uint16_t)bufin[offs++] << 8) | bufin[offs++];
rooms[longID] = shortID;
roomID = shortID;
if (autoserver) roomInit();
wprintw(wlog, "\n*Joining room %s", longID);
for (const auto& [key, value] : objects) {
objects.erase((char)key);
@ -579,6 +672,7 @@ void reciever(int sock_fd) {
}
memset(&(bufin[0]), 0, sizeof(bufin));
}
wrefresh(wlog);
}
void sessInit(int sock_fd, char* name, char* pass) {
@ -600,16 +694,20 @@ void sessInit(int sock_fd, char* name, char* pass) {
bufout[l++] = pass[c];
// Protocol
char* pstr = new char[4];
sprintf(pstr, "%d", protocol);
bufout[l++] = 3;
bufout[l++] = strlen(protocol);
for (int c = 0; c < strlen(protocol); c++)
bufout[l++] = protocol[c];
bufout[l++] = strlen(pstr);
for (int c = 0; c < strlen(pstr); c++)
bufout[l++] = pstr[c];
// Avatars
char* avstr = new char[4];
sprintf(avstr, "%d", avatars);
bufout[l++] = 7;
bufout[l++] = strlen(avatars);
for (int c = 0; c < strlen(avatars); c++)
bufout[l++] = avatars[c];
bufout[l++] = strlen(avstr);
for (int c = 0; c < strlen(avstr); c++)
bufout[l++] = avstr[c];
// Version
bufout[l++] = 9;
@ -663,6 +761,21 @@ void readPropertyList(unsigned char* in) {
}
}
std::map<char, char*> readOldPropertyList(unsigned char* in) {
std::map<char, char*> oldprops = {};
int l {3};
while (l < in[0]) {
char* value = new char[255];
char type = in[l++];
int len = in[l++];
memcpy(value, &in[l], len);
l+=len;
value[len]=0;
oldprops[type] = value;
}
return oldprops;
}
/*
void readPropertyList(unsigned char* in) {
int l {3};

32
src/props.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef PROPS_H
#define PROPS_H
#define PROP_APPNAME 1
#define PROP_USERNAME 2
#define PROP_PROTOCOL 3
#define PROP_ERROR 4
#define PROP_CHANNEL 5
#define PROP_PASSWORD 6
#define PROP_AVATARS 7
#define PROP_UPDATETIME 8
#define PROP_CLIENT 9
#define PROP_SERIAL 10
#define PROP_EMAIL 11
#define PROP_LOGONOFF 12
#define PROP_DURATION 13
#define PROP_GUEST 14
#define PROP_SERVERTYPE 15
#define PROP_BIZCARD 16
#define PROP_NEW_PASSWORD 20
#define PROP_PRIV 22
#define PROP_ASLEEP 23
#define PROP_EX_HTTP_SERVER 24
#define PROP_SCRIPT_SERVER 25
#define PROP_SMTP_SERVER 26
#define PROP_MAIL_DOMAIN 27
#define PROP_NEW_USERNAME 28
#define PROP_IN_HTTP_SERVER 29
#define PROP_INVENTORY 30
#endif

View File

@ -1,7 +1,7 @@
#ifndef H_VAR_ERROR
#define H_VAR_ERROR
#define VAR_OK 0 | 200
#define VAR_OK 0
#define VAR_BAD_USER 1
#define VAR_MAX_ORDINARY 2
#define VAR_MAX_PRIORITY 3