Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //By: Tim
- //Date: 2-24-11
- //Purpose: Basic Minecraft Login / Update Server.
- // Listens on port 5558 for incoming GET requests
- // and sends the requested files, if they are in the
- // shared folder
- //To DO:
- // A GUI? :-o
- /************\
- | Includes |
- \************/
- //standard library
- #include <stdlib.h>
- //print to console
- #include <iostream>
- //allow us to sleep (pause execution)
- #include <Windows.h>
- //allow us to multi-thread
- #include <process.h>
- //allow us to networkz
- #include <WinSock.h>
- //gives us strings for yarn and stuff
- #include <string>
- //allows us to read from files
- #include <fstream>
- //allows us to determine size of file
- #include <sys/stat.h>
- //don't have to say std:: before every god damn line
- using namespace std;
- /*************\
- | Functions |
- \*************/
- //used to accept clients + give out updated files
- void update_handle(void *params);
- //used to spoof the acceptence of login requests
- void login_handle(void *params);
- //sets up the socket, listens
- int webserver(int PORT);
- //sends files to the client
- bool sendfile(int sockfd, string file_name);
- //listens for login requests from minecraft
- void threaded_listen(void *port);
- //SIZE = the size of sockaddr_in
- #define SIZE sizeof(struct sockaddr_in)
- int main()
- {
- _beginthread(threaded_listen, 0, (void *)8123);
- webserver(8124);
- system("pause");
- return 0;
- }
- void threaded_listen(void *port)
- {
- //start another listen server, but on a different port and in a different thread
- webserver((int)port);
- }
- bool sendfile(int sockfd, string file_name)
- {
- //allows us to read from file
- ifstream fin;
- //stores the size of the file in some odd format
- struct stat fsize;
- //buffer
- char buff[65536];
- //number of bytes read from the file
- int num_read = 1;
- //total number of bytes read from the file
- int total_read = 0;
- //number of bytes sent to the client
- int num_sent = 0;
- //HTTP response to the client
- string output;
- //character array storing the size of the file
- char *file_size = (char*) malloc(sizeof(char));
- //attempt to open the file in binary format
- fin.open(file_name.c_str(), ios::binary);
- //did we open it?
- if (!fin.is_open())
- {
- cout << "couldn't open file" << endl;
- return false;
- }
- else
- {
- //grab the size of the file
- stat(file_name.c_str(), &fsize);
- //format it
- _itoa(fsize.st_size, file_size, 10);
- //build our HTTP response to the client
- output = "HTTP/1.1 200 OK\r\n";
- output += "x-amz-id-2: 57cxuiXKkSb32YEYIfZWMSyBA1STz/Dp/6NqjKhjWqJmHTTNtYFzAk9qdIrIzyhV\r\n";
- output += "x-amz-request-id: 8FB790874B07CF65\r\n";
- output += "Date: Tuesday, 25-Nov-97 01:00:00 EST\r\n";
- output += "Last-Modified: 25-Nov-97 01:00:00 EST\r\n";
- //whatever this stupid etag junk is, it's unique to each file (MD5, perhaps?)
- if (file_name == "shared\\lwjgl.jar")
- output += "ETag: \"7a07c4285fa9a6b204ba59f011f1cd77\"\r\n";
- else if (file_name == "shared\\jinput.jar")
- output += "ETag: \"a7835a73a130656aba23e34147a55367\"\r\n";
- else if (file_name == "shared\\lwjgl_util.jar")
- output += "ETag: \"f00470751cfc093ba760ca3cf10a512c\"\r\n";
- else if (file_name == "shared\\windows_natives.jar.lzma")
- output += "ETag: \"e3361fe429a3709e96cadec4b56a904f\"\r\n";
- else if (file_name == "shared\\minecraft.jar")
- output += "ETag: \"4203826f35e1036f089919032c3d19d1\"\r\n";
- output += "Accept-Ranges: bytes\r\n";
- output += "Content-type: application/x-java-archive\r\n";
- output += "Content-Length: " + (string)file_size + "\r\n";
- output += "Server: test\r\n\r\n";
- //send it
- send(sockfd, output.c_str(), output.length(), 0);
- //make sure we're at position 0
- fin.seekg(0);
- //while we have read something
- while(num_read > 0)
- {
- //attempt to read the next 1024 bytes, check how many we actually got
- //and update the counts
- fin.read(buff, 65536);
- num_read = fin.gcount();
- total_read += num_read;
- //if the number we have read so far is less than the total
- //and we just read something
- if (total_read <= fsize.st_size && num_read > 0)
- {
- //attempt to send the data to our client
- num_sent = send(sockfd, buff, num_read, 0);
- //did it send?
- if (num_sent <= 0)
- {
- //failed, let's wait a bit and try again
- cout << "error sending data, trying again" << endl;
- Sleep(5);
- num_sent = send(sockfd, buff, num_read, 0);
- if (num_sent <= 0)
- {
- cout << "errored sending data again, quitting" << endl;
- fin.close();
- return false;
- }
- }
- }
- }
- }
- //we sent!
- fin.close();
- return true;
- }
- int webserver(int PORT)
- {
- //Socket to listen for connections on
- struct sockaddr_in server;
- //not used
- struct sockaddr_in client;
- //File descriptor for the listen socket
- int sockfd;
- //Status code in case we get an error
- int status;
- //File descriptor for the socket on which we accept clients
- int newfd;
- //Error code.
- int errno;
- //Error code.
- int iResult;
- //prepare for sockets
- WSADATA wsaData;
- iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
- //Set up listen socket and client socket
- server.sin_family = AF_INET;
- server.sin_port = htons(PORT);
- server.sin_addr.s_addr = INADDR_ANY;
- client.sin_family = AF_INET;
- client.sin_port = htons(PORT);
- //Create the socket
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
- if (sockfd < 0)
- {
- cout << "Error creating listen socket." << endl;
- return 1;
- }
- //Bind the socket
- status = bind(sockfd, (struct sockaddr *)&server, SIZE);
- if (status < 0)
- {
- cout << "Could not bind listen socket." << endl;
- return 1;
- }
- //Listen for connection requests
- status = listen(sockfd, 1);
- if (status < 0)
- {
- cout << "Could not listen." << endl;
- return 1;
- }
- //Everything went right
- cout << "Listening on port " << PORT << endl;
- int len = SIZE;
- //forever
- while(1)
- {
- newfd = accept(sockfd, (struct sockaddr*)&client, &len);
- if (newfd < 0)
- {
- //whoooooops something went wrong
- cout << "Could not accept request" << endl;
- }
- else
- {
- //did it! print the file descriptor just for the lolz, then enter the new thread
- cout << "passing FD of " << newfd << endl;
- if (PORT == 8124)
- _beginthread(update_handle, 0, (void *)newfd);
- else
- _beginthread(login_handle, 0, (void *)newfd);
- }
- }
- }
- void update_handle(void * params)
- {
- //incoming file descriptor
- int newfd;
- //number of bytes read
- int num_read = 1;
- //number of bytes sent
- int num_sent = 0;
- //size of the buffer
- char buff[15000];
- //actual data storage
- string data;
- //set the file descriptor
- newfd = (int)params;
- //while we haven't gotten a disconnect
- while(num_read > 0)
- {
- //recieve data
- num_read = recv(newfd, buff, 14999, 0);
- //terminate the data
- buff[num_read] = '\0';
- //if we got anything, print it
- data = buff;
- //spot to parse data
- //minecraft insists on doing a HEAD before a GET - probably to check
- //if there's an updated version or not. Too god damn bad, notch.
- if (data.find("HEAD") != string::npos && data[5] == '/')
- send(newfd, "HTTP/1.0 501 Not Implemented\r\nServer: test\r\n\r\n", 46,0);
- else if (data.find("GET") != string::npos && data[4] == '/')
- {
- //what do they want?
- if (data.find("lwjgl.jar") != string::npos)
- sendfile(newfd, "shared\\lwjgl.jar");
- else if (data.find("jinput.jar") != string::npos)
- sendfile(newfd, "shared\\jinput.jar");
- else if (data.find("lwjgl_util.jar") != string::npos)
- sendfile(newfd, "shared\\lwjgl_util.jar");
- else if (data.find("windows_natives.jar") != string::npos)
- sendfile(newfd, "shared\\windows_natives.jar.lzma");
- else if (data.find("user") != string::npos)
- sendfile(newfd, "shared\\minecraft.jar");
- }
- }
- //they left us :(
- cout << "client disconnected" << endl;
- //end the thread, yo
- _endthread();
- }
- void login_handle(void * params)
- {
- //incoming file descriptor
- int newfd;
- //number of bytes read
- int num_read = 1;
- //number of bytes sent
- int num_sent = 0;
- //size of the buffer
- char buff[15000];
- //actual data storage
- string data;
- //set the file descriptor
- newfd = (int)params;
- //username the user wants
- string uname = "noob";
- //login OK response
- string Okay;
- //while we haven't gotten a disconnect
- while(num_read > 0)
- {
- num_read = recv(newfd, buff, 14999, 0);
- //terminate the data
- buff[num_read] = '\0';
- //if we got anything, print it
- data = buff;
- cout << data << endl;
- //did it send a login request?
- if (data.find("user") != string::npos)
- {
- //steal the username they tried to login with and use it as the accepted username
- uname = data.substr(data.find("user") + 5);
- uname = uname.substr(0, uname.find("password") - 1);
- cout << "caught login request from " << uname << endl;
- //lol
- if (uname == "wrycu" || uname == "Wrycu")
- uname = "noob";
- //build the reply
- Okay = "1295383684000:2699b4c0c738f69cfd066f538502f374:" + uname + ":11111111111";
- //attempt to send it
- num_sent = send(newfd, Okay.c_str(), Okay.length(), 0);
- //if it sent, close the socket and end the thread
- if (num_sent > 0)
- closesocket(newfd);
- _endthread();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement