Login Code
From libopenmetaverse - libomv - Developer Wiki
This code uses the Practical C++ Sockets wrapper library, available here: http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/practical/
#include <iostream> #include <string> #include <curl/curl.h> #include "PracticalSocket.h" using namespace std; #define VERSION "myslclient 0.0.1" #define EMAIL "your@email.here" #define SERVER_URL "https://login.agni.lindenlab.com/cgi-bin/login.cgi" typedef struct login_parameters { string session_id; string secure_session_id; string start_location; string first_name; string last_name; int region_x; int region_y; string home; string message; int circuit_code; int sim_port; string sim_ip; string look_at; string agent_id; int seconds_since_epoch; } login_parameters; struct login_packet { char priority; char counter[3]; unsigned int id; char agent_id[16]; char unknown[20]; }; // This should be a 24-bit number unsigned char counter = 1; #define isdigit(c) (c >= '0' && c <= '9') __inline static int atoin(char *s, unsigned int n) { int i = 0; while (isdigit(*s) && n) { i = i*10 + *(s++) - '0'; --n; } return i; } static int hex2num(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return -1; } static int hex2byte(const char* hex) { int a, b; a = hex2num(*hex++); if (a < 0) return -1; b = hex2num(*hex++); if (b < 0) return -1; return (a << 4) | b; } int hexstr2bin(const char* hex, char* buf, size_t len) { unsigned int i; unsigned char a; const char* ipos = hex; char* opos = buf; for (i = 0; i < len; i++) { a = hex2byte(ipos); if (a < 0) return -1; *opos++ = a; ipos += 2; } return 0; } string get_string_value(char* buffer, const char* name) { char* pos = strstr(buffer, name); char* pos2 = NULL; unsigned int i = 0; string value = ""; if (pos) { if (pos = strstr(pos, "<string>")) { pos += 8; if (pos2 = strstr(pos, "</string>")) { value = string(pos); value = value.substr(0, (pos2 - pos)); } } } // Replace newline characters i = value.find_first_of('\n'); while (i != string::npos) { value.replace(i, 1, " "); i = value.find_first_of('\n', i); } return value; } unsigned int get_int_value(char* buffer, const char* name) { char* pos = strstr(buffer, name); char* pos2 = NULL; unsigned int value = 0; if (pos) { if (pos = strstr(pos, "<i4>")) { pos += 4; if (pos2 = strstr(pos, "</i4>")) { if (pos2 > pos) { value = atoin(pos, (int)(pos2 - pos)); } } } } return value; } string packed_uuid(string uuid) { if (uuid.length() == 36) { uuid.erase(8, 1); uuid.erase(12, 1); uuid.erase(16, 1); uuid.erase(20, 1); } else if (uuid.length() != 32) { uuid = ""; } return uuid; } int login_to_sim(struct login_parameters login) { char* payload; int payload_len; char recv_buffer[2048]; int recv_message_len; string source_address; unsigned short source_port; struct login_packet packet; packet.priority = 0x40; packet.counter[0] = 0x00; packet.counter[1] = 0x00; packet.counter[2] = counter; packet.id = 0x0300FFFF; hexstr2bin(packed_uuid(login.agent_id).c_str(), packet.agent_id, 16); payload = (char*)&packet.priority; payload_len = 44; try { UDPSocket sock; sock.sendTo(payload, payload_len, login.sim_ip, login.sim_port); // We only send one packet, and the last 20 bytes are bad. Help! for (;;) { // Block until receive message from a client recv_message_len = sock.recvFrom(recv_buffer, 2048, source_address, source_port); cout << "Received packet from " << source_address << ":" << source_port << endl; //sock.sendTo(echoBuffer, recvMsgSize, sourceAddress, sourcePort); } } catch (SocketException &e) { cerr << e.what() << endl; return -1; } return 0; } size_t login_reply(void *buffer, size_t size, size_t nmemb, void *userp) { char* reply = (char*)buffer; string msg; struct login_parameters login; msg = get_string_value(reply, "<name>reason</name>"); if (msg.length()) { cout << "Login failed.\nReason: " << msg << "\n"; msg = get_string_value(reply, "<name>message</name>"); if (msg.length()) { cout << "Message: " << msg << "\n"; } else { cout << "Couldn't find an error message, dumping server response\n\n" << reply << "\n"; } } else { msg = get_string_value(reply, "login</name><value><string>true"); if (msg.length()) { cout << "Login successful\n"; // Put all of the login parameters in to our struct login.session_id = get_string_value(reply, "<name>session_id</name>"); login.secure_session_id = get_string_value(reply, "<name>secure_session_id</name>"); login.start_location = get_string_value(reply, "<name>start_location</name>"); login.first_name = get_string_value(reply, "<name>first_name</name>"); login.last_name = get_string_value(reply, "<name>last_name</name>"); login.region_x = get_int_value(reply, "<name>region_x</name>"); login.region_y = get_int_value(reply, "<name>region_y</name>"); login.home = get_string_value(reply, "<name>home</name>"); login.message = get_string_value(reply, "<name>message</name>"); login.circuit_code = get_int_value(reply, "<name>circuit_code</name>"); login.sim_port = get_int_value(reply, "<name>sim_port</name>"); login.sim_ip = get_string_value(reply, "<name>sim_ip</name>"); login.look_at = get_string_value(reply, "<name>look_at</name>"); login.agent_id = get_string_value(reply, "<name>agent_id</name>"); login.seconds_since_epoch = get_int_value(reply, "<name>seconds_since_epoch</name>"); login_to_sim(login); } else { cout << "Unknown login error, dumping server response\n\n" << reply << "\n"; } } return nmemb; } int main(int const argc, const char** const argv) { CURL* curl; CURLcode response; char login_error[CURL_ERROR_SIZE] = {0x00}; struct curl_slist* headers = NULL; string login_request; string first = "First"; string last = "Last"; string passwd = "password_hash_here"; string mac = "00:D0:5D:36:0B:34"; login_request = "<?xml version=\"1.0\"?><methodCall><methodName>login_to_simulator</methodName><params><param><value><struct>" "<member><name>first</name><value><string>" + first + "</string></value></member>" "<member><name>last</name><value><string>" + last + "</string></value></member>" "<member><name>passwd</name><value><string>" + passwd + "</string></value></member>" "<member><name>start</name><value><string>last</string></value></member>" "<member><name>major</name><value><string>1</string></value></member>" "<member><name>minor</name><value><string>9</string></value></member>" "<member><name>patch</name><value><string>0</string></value></member>" "<member><name>build</name><value><string>21</string></value></member>" "<member><name>platform</name><value><string>Win</string></value></member>" "<member><name>mac</name><value><string>" + mac + "</string></value></member>" "<member><name>viewer_digest</name><value><string>68920a26-9f41-b742-a5e6-db6a713dcd96</string></value></member>" "<member><name>user-agent</name><value><string>" + VERSION + "</string></value></member>" "<member><name>author</name><value><string>" + EMAIL + "</string></value></member>" "</struct></value></param></params></methodCall>"; curl = curl_easy_init(); if (curl) { headers = curl_slist_append(headers, "Accept-Encoding: gzip"); headers = curl_slist_append(headers, "Content-Type: text/xml"); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, login_error); curl_easy_setopt(curl, CURLOPT_URL, SERVER_URL); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 9); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, login_request.c_str()); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, login_request.length()); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, login_reply); response = curl_easy_perform(curl); if (response) { cout << "Error connecting to the login server.\n" << login_error << "\n"; } curl_slist_free_all(headers); curl_easy_cleanup(curl); } return 0; }