From f32ec710ff92ac23023c74c6accecb777f260441 Mon Sep 17 00:00:00 2001 From: winsped <248554933+snow32a@users.noreply.github.com> Date: Thu, 6 Aug 2026 17:40:27 +0300 Subject: [PATCH] implemented keepalive --- TODO.md | 2 +- discordapi.c | 28 +- discordapi.h | 4 +- http.c | 765 ++++++++++++++++++++++++++++----------------------- http.h | 18 +- main.c | 10 + 6 files changed, 477 insertions(+), 350 deletions(-) diff --git a/TODO.md b/TODO.md index 791b972..d0498ce 100644 --- a/TODO.md +++ b/TODO.md @@ -10,9 +10,9 @@ - [X] ChatView with proper message alignment - [X] Showing mention counts - [X] Keep-Alive HTTP implementation +- [X] Switch to keep-alive HTTP use - [ ] Add support for GCs - [ ] Rendering replies -- [ ] Switch to keep-alive HTTP - [ ] Add support for guild folders - [ ] Use the root guild folder to order the guilds properly - [ ] File uploading diff --git a/discordapi.c b/discordapi.c index c432341..6ac2856 100755 --- a/discordapi.c +++ b/discordapi.c @@ -1,6 +1,7 @@ #include "discordtypes.h" #include "http.h" #include "config.h" +#include #include #include #include @@ -12,6 +13,8 @@ hmap GuildsTable = NULL; hmap ChannelsTable = NULL; DiscordChannel *PrivateChannels = NULL; +HTTPConnection* maincon; +HTTPConnection* cdncon; int PrivateChannelCount = 0; static uint64_t GuildHash(const void *item, uint64_t seed0, uint64_t seed1) { const DiscordGuild *e = item; @@ -33,6 +36,15 @@ static void ChannelFree(void *item) {} extern void onDiscordGuildLoad(DiscordGuild *guild, char *id); extern void onDiscordUpdatedGuildReadState(DiscordGuild gld); extern void onDiscordReady(DiscordUser user, DiscordGuild *guilds, int guildscount); +int DiscordHTTPConnect(){ + maincon=HTTPConnect("discord.com"); + cdncon=HTTPConnect("cdn.discordapp.com"); + return maincon->connected && cdncon->connected; +} +void DiscordHTTPClose(){ + CloseHTTPConnection(maincon); + CloseHTTPConnection(cdncon); +} int DiscordSendMessage(const char *channelID, const char *content) { cJSON *payload = cJSON_CreateObject(); cJSON *name = cJSON_CreateString(content); @@ -46,8 +58,8 @@ int DiscordSendMessage(const char *channelID, const char *content) { char *payld = cJSON_Print(payload); long resplen; char headers[17 + strlen(token) + 1]; - wsprintf(headers, "Authorization: %s\r\n", token); - SendShortHTTPReq("discord.com", "POST", endpoint, headers, user_agent, + wsprintf(headers, "Authorization: %s", token); + SendHTTPRequest(maincon,"POST", endpoint, headers, user_agent, "application/json", payld, strlen(payld), &forNothingGng, &resplen); free(payld); @@ -74,8 +86,8 @@ char *DiscordFetchTmpPfp(char *userID, char *hash) { char *HTTPResp; long resplen; char headers[17 + strlen(token) + 1]; - wsprintf(headers, "Authorization: %s\r\n", token); - SendShortHTTPReq("cdn.discordapp.com", "GET", endpoint, headers, user_agent, + wsprintf(headers, "Authorization: %s", token); + SendHTTPRequest(cdncon, "GET", endpoint, headers, user_agent, "application/json", NULL, 0, &HTTPResp, &resplen); free(endpoint); @@ -105,8 +117,8 @@ char *DiscordFetchTmpGuildIcon(char *guildID, char *hash) { char *HTTPResp; long resplen; char headers[17 + strlen(token) + 1]; - wsprintf(headers, "Authorization: %s\r\n", token); - SendShortHTTPReq("cdn.discordapp.com", "GET", endpoint, headers, user_agent, + wsprintf(headers, "Authorization: %s", token); + SendHTTPRequest(cdncon, "GET", endpoint, headers, user_agent, "application/json", NULL, 0, &HTTPResp, &resplen); free(endpoint); @@ -146,9 +158,9 @@ int DiscordGetChannelHistory(const char *channelID, unsigned int amount, long resplen; char headers[17 + strlen(token) + 1]; - wsprintf(headers, "Authorization: %s\r\n", token); + wsprintf(headers, "Authorization: %s", token); - SendShortHTTPReq("discord.com", "GET", endpoint, headers, user_agent, + SendHTTPRequest(maincon, "GET", endpoint, headers, user_agent, "application/json", NULL, 0, &HTTPResp, &resplen); cJSON *resp = cJSON_Parse(HTTPResp); if (!resp) diff --git a/discordapi.h b/discordapi.h index 4c60478..8fcf1bd 100755 --- a/discordapi.h +++ b/discordapi.h @@ -12,4 +12,6 @@ int DiscordListGuildChannels(char* guildID, DiscordChannel** out); int DiscordGetChannelHistory(const char* channelID, unsigned int amount, DiscordMessage** msgs); char *DiscordFetchTmpPfp(char *userID, char *hash); char *DiscordFetchTmpGuildIcon(char *guildID, char *hash); -int DiscordListPrivateChannels(DiscordChannel** out); \ No newline at end of file +int DiscordListPrivateChannels(DiscordChannel** out); +int DiscordHTTPConnect(); +void DiscordHTTPClose(); \ No newline at end of file diff --git a/http.c b/http.c index 4fc4748..4095872 100755 --- a/http.c +++ b/http.c @@ -7,378 +7,465 @@ #include #include -// keepalive state -typedef struct { - SOCKET sock; - SSL* ssl; - SSL_CTX* ctx; - char hostname[256]; - int connected; -} HTTPConnection; - -static void AppendHeader(char* buf, - const char* key, const char* value) -{ - strcat(buf, key); - strcat(buf, ": "); - strcat(buf, value); - strcat(buf, "\r\n"); +static void AppendHeader(char *buf, const char *key, const char *value) { + strcat(buf, key); + strcat(buf, ": "); + strcat(buf, value); + strcat(buf, "\r\n"); } -char* ProcessChunkedTransfer(char* chunked, size_t chunked_len, size_t *out_len) { - char* result = malloc(chunked_len); - size_t written = 0; - char* curpos = chunked; +char *ProcessChunkedTransfer(char *chunked, size_t chunked_len, + size_t *out_len) { + char *result = malloc(chunked_len); + size_t written = 0; + char *curpos = chunked; - while(1) { - char* crlf = strstr(curpos, "\r\n"); - if(!crlf) break; + while (1) { + char *crlf = strstr(curpos, "\r\n"); + if (!crlf) + break; - int chunklen = (int)strtol(curpos, NULL, 16); - if(chunklen == 0) break; + int chunklen = (int)strtol(curpos, NULL, 16); + if (chunklen == 0) + break; - char* data = crlf + 2; - memcpy(result + written, data, chunklen); - written += chunklen; - curpos = data + chunklen + 2; - } - - *out_len = written; - return result; -} - -HTTPConnection* ConnectOverHTTP(const char* hostname) { - HTTPConnection* conn = malloc(sizeof(HTTPConnection)); - RtlZeroMemory(conn, sizeof(HTTPConnection)); - - strncpy(conn->hostname, hostname, 255); - conn->hostname[255] = '\0'; - - conn->sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - - if (conn->sock == INVALID_SOCKET) { - MessageBoxA(NULL, "socket failed :(", "sad http announcement", 0); - free(conn); - return NULL; - } - - struct sockaddr_in server; - RtlZeroMemory(&server, sizeof(server)); - server.sin_family = AF_INET; - server.sin_port = htons(443); - server.sin_addr = **(struct in_addr**)gethostbyname(hostname)->h_addr_list; // why is a part of this in bold - - if (connect(conn->sock, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) { - MessageBoxA(NULL, "connect failed :(", "sad http announcement", 0); - closesocket(conn->sock); - free(conn); - return NULL; - } - - conn->ctx = SSL_CTX_new(TLS_client_method()); - - if (!conn->ctx) { - MessageBoxA(NULL, "SSL_CTX_new failed :(", "sad http announcement", 0); - closesocket(conn->sock); - free(conn); - return NULL; - } - - conn->ssl = SSL_new(conn->ctx); - - if (!conn->ssl) { - MessageBoxA(NULL, "SSL_new failed :(", "sad http announcement", 0); - SSL_CTX_free(conn->ctx); - closesocket(conn->sock); - free(conn); - return NULL; - } - - SSL_set_fd(conn->ssl, (int)conn->sock); - SSL_set_tlsext_host_name(conn->ssl, hostname); - - if (SSL_connect(conn->ssl) <= 0) { - MessageBoxA(NULL, "SSL_connect failed :(", "sad http announcement", 0); - SSL_free(conn->ssl); - SSL_CTX_free(conn->ctx); - closesocket(conn->sock); - free(conn); - return NULL; - } - - conn->connected = 1; - return conn; -} -int SendHTTPRequest(HTTPConnection* conn, const char* method, const char* endpoint, - const char* user_agent, const char* content_type, void* payload, - unsigned long payload_size, char** response, long* responselen) -{ - if (!conn || !conn->connected) { - MessageBoxA(NULL, "connection not established :(", "sad http announcement", 0); - return 1; - } - - char headerbuf[2048]; - RtlZeroMemory(headerbuf, sizeof(headerbuf)); - - wsprintfA(headerbuf, "%s %s HTTP/1.1\r\n", method, endpoint); - strcat(headerbuf, "Host: "); - strcat(headerbuf, conn->hostname); - strcat(headerbuf, "\r\n"); - strcat(headerbuf, "User-Agent: "); - strcat(headerbuf, user_agent); - strcat(headerbuf, "\r\n"); - - if (payload) { - strcat(headerbuf, "Content-Type: "); - strcat(headerbuf, content_type); - strcat(headerbuf, "\r\n"); - - char contentlen[128]; - RtlZeroMemory(contentlen, sizeof(contentlen)); - wsprintfA(contentlen, "Content-Length: %lu\r\n", payload_size); - strcat(headerbuf, contentlen); - } - - strcat(headerbuf, "Connection: keep-alive\r\n"); - strcat(headerbuf, "\r\n"); - - if (SSL_write(conn->ssl, headerbuf, (int)strlen(headerbuf)) <= 0) { - MessageBoxA(NULL, "SSL_write headers failed :(", "sad http announcement", 0); - return 1; - } - - if (payload && payload_size > 0) { - if (SSL_write(conn->ssl, payload, (int)payload_size) <= 0) { - MessageBoxA(NULL, "SSL_write payload failed :(", "sad http announcement", 0); - return 1; - } - } - - char* buffer = malloc(8192); - size_t sizeofbuf = 8192; - size_t total_bytes = 0; - int bytes_read; - - while ((bytes_read = SSL_read(conn->ssl, buffer + total_bytes, (int)(sizeofbuf - total_bytes - 1))) > 0) { - total_bytes += bytes_read; - - if (total_bytes + 1 >= sizeofbuf) { - sizeofbuf += 8192; - char* newbuf = realloc(buffer, sizeofbuf); - - if (!newbuf) { - MessageBoxA(NULL, "realloc failed :(", "sad http announcement", 0); - free(buffer); - return -1; - } - - buffer = newbuf; - } - } - - buffer[total_bytes] = '\0'; - - char* endofhdr = strstr(buffer, "\r\n\r\n"); - - if (!endofhdr) { - MessageBoxA(NULL, "malformed response :(", "sad http announcement", 0); - free(buffer); - return -1; - } - - char* body_start = endofhdr + 4; - size_t body_len = total_bytes - (body_start - buffer); - - if (strstr(buffer, "Transfer-Encoding: chunked")) { - size_t outlen; - *response = ProcessChunkedTransfer(body_start, body_len, &outlen); - *responselen = (long)outlen; - free(buffer); - } else { - char* copy = malloc(body_len + 1); - memcpy(copy, body_start, body_len); - copy[body_len] = '\0'; - *response = copy; - *responselen = (long)body_len; - free(buffer); - } - - return 0; -} -int CloseHTTPConnection(HTTPConnection* conn) { - if (!conn) { - return 1; - } - - if (conn->ssl) { - SSL_shutdown(conn->ssl); - SSL_free(conn->ssl); - } - - if (conn->ctx) { - SSL_CTX_free(conn->ctx); - } - - if (conn->sock != INVALID_SOCKET) { - closesocket(conn->sock); - } - - free(conn); - return 0; -} -int SendShortHTTPReq(const char* hostname,const char* reqtype, const char* endpoint, const char* extra_headers, const char* user_agent, const char* content_type, void* payload, unsigned long payload_size, char** response, long* responselen) -{ - SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sock == INVALID_SOCKET) { - MessageBoxA(NULL, "socket failed", "Aa", 0); - return 1; - } - - struct sockaddr_in server; - RtlZeroMemory(&server, sizeof(server)); - server.sin_family = AF_INET; - server.sin_port = htons(443); // HTTPS brotatochippiee - server.sin_addr = **(struct in_addr**)gethostbyname(hostname)->h_addr_list; - - if (connect(sock, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) { - MessageBoxA(NULL, "connect failed", "Aa", 0); - closesocket(sock); - return 1; + char *data = crlf + 2; + memcpy(result + written, data, chunklen); + written += chunklen; + curpos = data + chunklen + 2; } - // this debugging thing served us well yall MessageBoxA(NULL, "onto ze ctx", "Aa", 0); - SSL_CTX* ctx = SSL_CTX_new(TLS_client_method()); - if (!ctx) { + *out_len = written; + return result; +} + +HTTPConnection *HTTPConnect(const char *hostname) { + HTTPConnection *conn = malloc(sizeof(HTTPConnection)); + RtlZeroMemory(conn, sizeof(HTTPConnection)); + + strncpy(conn->hostname, hostname, 255); + conn->hostname[255] = '\0'; + + conn->sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (conn->sock == INVALID_SOCKET) { + char msg[128]; + wsprintfA(msg, "socket failed: WSAGetLastError=%d", WSAGetLastError()); + MessageBoxA(NULL, msg, "sad http announcement", 0); + free(conn); + return NULL; + } + + struct sockaddr_in server; + RtlZeroMemory(&server, sizeof(server)); + server.sin_family = AF_INET; + server.sin_port = htons(443); + server.sin_addr = **(struct in_addr **)gethostbyname(hostname) + ->h_addr_list; // why is a part of this in bold + + if (connect(conn->sock, (struct sockaddr *)&server, sizeof(server)) == + SOCKET_ERROR) { + MessageBoxA(NULL, "connect failed :(", "sad http announcement", 0); + closesocket(conn->sock); + free(conn); + return NULL; + } + + conn->ctx = SSL_CTX_new(TLS_client_method()); + + if (!conn->ctx) { + MessageBoxA(NULL, "SSL_CTX_new failed :(", "sad http announcement", 0); + closesocket(conn->sock); + free(conn); + return NULL; + } + + conn->ssl = SSL_new(conn->ctx); + + if (!conn->ssl) { + MessageBoxA(NULL, "SSL_new failed :(", "sad http announcement", 0); + SSL_CTX_free(conn->ctx); + closesocket(conn->sock); + free(conn); + return NULL; + } + + SSL_set_fd(conn->ssl, (int)conn->sock); + SSL_set_tlsext_host_name(conn->ssl, hostname); + + if (SSL_connect(conn->ssl) <= 0) { + MessageBoxA(NULL, "SSL_connect failed :(", "sad http announcement", 0); + SSL_free(conn->ssl); + SSL_CTX_free(conn->ctx); + closesocket(conn->sock); + free(conn); + return NULL; + } + + conn->connected = 1; + return conn; +} +char *GetHeaderValue(char *source, char *field) { + size_t flen = strlen(field); + for (char *curs = source; curs; curs = strstr(curs + 1, "\r\n") + ? strstr(curs + 1, "\r\n") + 2 + : NULL) { + if (strncmp(field, curs, flen) == 0 && curs[flen] == ':') { + char *dat = curs + flen + 1; + while (*dat == ' ') + dat++; + char *end = strstr(curs + 1, "\r\n"); + char *ret = malloc(end - dat + 1); + memcpy(ret, dat, end - dat); + ret[end - dat] = '\0'; + return ret; + } + } + return NULL; +} +int SendHTTPRequest(HTTPConnection *conn, const char *method, + const char *endpoint, const char *extra_headers, + const char *user_agent, const char *content_type, + void *payload, unsigned long payload_size, char **response, + long *responselen) { + if (!conn || !conn->connected) { + MessageBoxA(NULL, "connection not established :(", + "sad http announcement", 0); + return 1; + } + + char headerbuf[4096]; + RtlZeroMemory(headerbuf, sizeof(headerbuf)); + + wsprintfA(headerbuf, "%s %s HTTP/1.1\r\n", method, endpoint); + strcat(headerbuf, "Host: "); + strcat(headerbuf, conn->hostname); + strcat(headerbuf, "\r\n"); + strcat(headerbuf, extra_headers); + strcat(headerbuf, "\r\n"); + strcat(headerbuf, "User-Agent: "); + strcat(headerbuf, user_agent); + strcat(headerbuf, "\r\n"); + + if (payload) { + strcat(headerbuf, "Content-Type: "); + strcat(headerbuf, content_type); + strcat(headerbuf, "\r\n"); + + char contentlen[128]; + RtlZeroMemory(contentlen, sizeof(contentlen)); + wsprintfA(contentlen, "Content-Length: %lu\r\n", payload_size); + strcat(headerbuf, contentlen); + } + + strcat(headerbuf, "Connection: keep-alive\r\n"); + strcat(headerbuf, "\r\n"); + char dbg[64]; + wsprintfA(dbg, "headerbuf len: %d", (int)strlen(headerbuf)); + MessageBoxA(NULL, dbg, "debug", 0); + if (SSL_write(conn->ssl, headerbuf, (int)strlen(headerbuf)) <= 0) { + MessageBoxA(NULL, "SSL_write headers failed :(", + "sad http announcement", 0); + return 1; + } + + if (payload && payload_size > 0) { + if (SSL_write(conn->ssl, payload, (int)payload_size) <= 0) { + MessageBoxA(NULL, "SSL_write payload failed :(", + "sad http announcement", 0); + return 1; + } + } + + char *buffer = malloc(8192); + memset(buffer, 0, 8192); + size_t sizeofbuf = 8192; + size_t total_bytes = 0; + int bytes_read; + int headerlen; + while (strstr(buffer, "\r\n\r\n") == NULL) { + bytes_read = SSL_read(conn->ssl, buffer + total_bytes, + (int)(sizeofbuf - total_bytes - 1)); + total_bytes += bytes_read; + + if (total_bytes + 1 >= sizeofbuf) { + sizeofbuf += 8192; + char *newbuf = realloc(buffer, sizeofbuf); + + if (!newbuf) { + MessageBoxA(NULL, "realloc failed :(", "sad http announcement", + 0); + free(buffer); + return -1; + } + + buffer = newbuf; + } + } + char *endofhdr = strstr(buffer, "\r\n\r\n"); + headerlen = endofhdr - buffer; + char *headers = malloc(headerlen + 1); + memcpy(headers, buffer, headerlen); + headers[headerlen] = '\0'; + + char *cclen = GetHeaderValue(headers, "Content-Length"); + unsigned long long clen = cclen ? strtoull(cclen, NULL, 10) : 0; + free(cclen); + + char *body_start = buffer + headerlen + 4; + size_t body_have = + total_bytes - (body_start - buffer); // body bytes already buffered + + int is_chunked = 0; + char *cte = GetHeaderValue(headers, "Transfer-Encoding"); + if (cte) { + if (strstr(cte, "chunked")) + is_chunked = 1; + free(cte); + } + free(headers); + if (is_chunked) { + while (!strstr(body_start, "0\r\n\r\n")) { + if (total_bytes + 1 >= sizeofbuf) { + sizeofbuf += 8192; + char *newbuf = realloc(buffer, sizeofbuf); + if (!newbuf) { + free(buffer); + return -1; + } + buffer = newbuf; + body_start = buffer + headerlen + 4; + } + int n = SSL_read(conn->ssl, buffer + total_bytes, + (int)(sizeofbuf - total_bytes - 1)); + if (n <= 0) + break; + total_bytes += n; + buffer[total_bytes] = '\0'; + } + } else { + while (body_have < clen) { + if (total_bytes + 1 >= sizeofbuf) { + sizeofbuf += 8192; + char *newbuf = realloc(buffer, sizeofbuf); + if (!newbuf) { + free(buffer); + return -1; + } + buffer = newbuf; + body_start = buffer + headerlen + 4; + } + int n = SSL_read(conn->ssl, buffer + total_bytes, + (int)(sizeofbuf - total_bytes - 1)); + if (n <= 0) + break; + total_bytes += n; + body_have += n; + } + } + + buffer[total_bytes] = '\0'; + + if (!endofhdr) { + MessageBoxA(NULL, "malformed response :(", "sad http announcement", 0); + free(buffer); + return -1; + } + + size_t body_len = total_bytes - (body_start - buffer); + + if (is_chunked) { + size_t outlen; + *response = ProcessChunkedTransfer(body_start, body_len, &outlen); + *responselen = (long)outlen; + free(buffer); + } else { + char *copy = malloc(body_len + 1); + memcpy(copy, body_start, body_len); + copy[body_len] = '\0'; + *response = copy; + *responselen = (long)body_len; + free(buffer); + } + return 0; +} +int CloseHTTPConnection(HTTPConnection *conn) { + if (!conn) { + return 1; + } + + if (conn->ssl) { + SSL_shutdown(conn->ssl); + SSL_free(conn->ssl); + } + + if (conn->ctx) { + SSL_CTX_free(conn->ctx); + } + + if (conn->sock != INVALID_SOCKET) { + closesocket(conn->sock); + } + + free(conn); + return 0; +} +int SendShortHTTPReq(const char *hostname, const char *reqtype, + const char *endpoint, const char *extra_headers, + const char *user_agent, const char *content_type, + void *payload, unsigned long payload_size, char **response, + long *responselen) { + SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock == INVALID_SOCKET) { + MessageBoxA(NULL, "socket failed", "Aa", 0); + return 1; + } + + struct sockaddr_in server; + RtlZeroMemory(&server, sizeof(server)); + server.sin_family = AF_INET; + server.sin_port = htons(443); // HTTPS brotatochippiee + server.sin_addr = **(struct in_addr **)gethostbyname(hostname)->h_addr_list; + + if (connect(sock, (struct sockaddr *)&server, sizeof(server)) == + SOCKET_ERROR) { + MessageBoxA(NULL, "connect failed", "Aa", 0); + closesocket(sock); + return 1; + } + + // this debugging thing served us well yall MessageBoxA(NULL, "onto ze ctx", + // "Aa", 0); + SSL_CTX *ctx = SSL_CTX_new(TLS_client_method()); + if (!ctx) { MessageBoxA(NULL, "SSL_CTX_new failed", "Aa", 0); - unsigned long err = ERR_get_error(); - if (err == 0) { - MessageBoxA(NULL, "unknown OpenSSL error", "title", MB_ICONERROR); - return 1; - } + unsigned long err = ERR_get_error(); + if (err == 0) { + MessageBoxA(NULL, "unknown OpenSSL error", "title", MB_ICONERROR); + return 1; + } - char buf[256]; - ERR_error_string_n(err, buf, sizeof(buf)); + char buf[256]; + ERR_error_string_n(err, buf, sizeof(buf)); - MessageBoxA(NULL, buf, "title", MB_ICONERROR); - return 1; - } + MessageBoxA(NULL, buf, "title", MB_ICONERROR); + return 1; + } - SSL* ssl = SSL_new(ctx); - if (!ssl) { - MessageBoxA(NULL, "SSL_new failed qwq", "Aa", 0); - return 1; - } + SSL *ssl = SSL_new(ctx); + if (!ssl) { + MessageBoxA(NULL, "SSL_new failed qwq", "Aa", 0); + return 1; + } - // Attach socket to SSL - SSL_set_fd(ssl, (int)sock); + // Attach socket to SSL + SSL_set_fd(ssl, (int)sock); - // SNI (importante shi) - SSL_set_tlsext_host_name(ssl, hostname); + // SNI (importante shi) + SSL_set_tlsext_host_name(ssl, hostname); - if (SSL_connect(ssl) <= 0) { - MessageBoxA(NULL, "SSL_connect failed", "Aa", 0); - SSL_free(ssl); - SSL_CTX_free(ctx); - closesocket(sock); - return 1; - } + if (SSL_connect(ssl) <= 0) { + MessageBoxA(NULL, "SSL_connect failed", "Aa", 0); + SSL_free(ssl); + SSL_CTX_free(ctx); + closesocket(sock); + return 1; + } - - SSL_write(ssl, reqtype, (int)strlen(reqtype)); // Sends request type - SSL_write(ssl, " ", 1); // stupid fuckass space + SSL_write(ssl, reqtype, (int)strlen(reqtype)); // Sends request type + SSL_write(ssl, " ", 1); // stupid fuckass space SSL_write(ssl, endpoint, (int)strlen(endpoint)); // endpoint - SSL_write(ssl, " HTTP/1.1\r\n", 11); // the protocol thing.. ykw i will be more formal - SSL_write(ssl, "Host: ", 6); // Host beginning + SSL_write(ssl, " HTTP/1.1\r\n", + 11); // the protocol thing.. ykw i will be more formal + SSL_write(ssl, "Host: ", 6); // Host beginning SSL_write(ssl, hostname, (int)(strlen(hostname))); // Host data - SSL_write(ssl, "\r\n", 2); // Host end - SSL_write(ssl, "User-Agent: ", 12); // User Agent beginning + SSL_write(ssl, "\r\n", 2); // Host end + SSL_write(ssl, "User-Agent: ", 12); // User Agent beginning SSL_write(ssl, user_agent, (int)(strlen(user_agent))); // User Agent data - SSL_write(ssl, "\r\n", 2); // User Agent end - + SSL_write(ssl, "\r\n", 2); // User Agent end if (payload != 0) { SSL_write(ssl, "Content-Type: ", 14); // Content Type beginning SSL_write(ssl, content_type, (int)strlen(content_type)); - SSL_write(ssl, "\r\n", 2); // Content Type end - - SSL_write(ssl, "Content-Length: ", 16); // Content Length beginning - char lenstr[64]; - RtlZeroMemory(lenstr,64); - wsprintfA(lenstr,"%d",payload_size); - SSL_write(ssl, lenstr, (int)(strlen(lenstr))); // Content Length data - SSL_write(ssl, "\r\n", 2); // Content Length end -} + SSL_write(ssl, "\r\n", 2); // Content Type end + SSL_write(ssl, "Content-Length: ", 16); // Content Length beginning + char lenstr[64]; + RtlZeroMemory(lenstr, 64); + wsprintfA(lenstr, "%d", payload_size); + SSL_write(ssl, lenstr, (int)(strlen(lenstr))); // Content Length data + SSL_write(ssl, "\r\n", 2); // Content Length end + } SSL_write(ssl, extra_headers, (int)(strlen(extra_headers))); // Extra Header - SSL_write(ssl, "Connection: close\r\n", 19); //Short-term connection - SSL_write(ssl, "\r\n", 2); //Ends the header - if(payload) - SSL_write(ssl, payload, (int)payload_size); //Payload + SSL_write(ssl, "\r\n", 2); + SSL_write(ssl, "Connection: close\r\n", 19); // Short-term connection + SSL_write(ssl, "\r\n", 2); // Ends the header + if (payload) + SSL_write(ssl, payload, (int)payload_size); // Payload - char* buffer = malloc(4096); - size_t sizeofbuf = 4096; - size_t total_bytes = 0; - int bytes_read; + char *buffer = malloc(4096); + size_t sizeofbuf = 4096; + size_t total_bytes = 0; + int bytes_read; - while ((bytes_read = SSL_read(ssl, buffer + total_bytes, (int)(sizeofbuf - total_bytes - 1))) > 0) { - total_bytes += bytes_read; + while ((bytes_read = SSL_read(ssl, buffer + total_bytes, + (int)(sizeofbuf - total_bytes - 1))) > 0) { + total_bytes += bytes_read; - if (total_bytes + 1 >= sizeofbuf) { - sizeofbuf += 4096; - char* newbuf = realloc(buffer, sizeofbuf); - if (!newbuf) { - //what the fuck had possibly happened on bros pc :sob: - free(buffer); - SSL_shutdown(ssl); - SSL_free(ssl); - SSL_CTX_free(ctx); - closesocket(sock); - return -1; - } - buffer = newbuf; - } - } - buffer[total_bytes] = '\0'; + if (total_bytes + 1 >= sizeofbuf) { + sizeofbuf += 4096; + char *newbuf = realloc(buffer, sizeofbuf); + if (!newbuf) { + // what the fuck had possibly happened on bros pc :sob: + free(buffer); + SSL_shutdown(ssl); + SSL_free(ssl); + SSL_CTX_free(ctx); + closesocket(sock); + return -1; + } + buffer = newbuf; + } + } + buffer[total_bytes] = '\0'; - char *endofhdr = strstr(buffer, "\r\n\r\n"); - if (!endofhdr) { - free(buffer); - SSL_shutdown(ssl); SSL_free(ssl); SSL_CTX_free(ctx); - closesocket(sock); - return -1; - } + char *endofhdr = strstr(buffer, "\r\n\r\n"); + if (!endofhdr) { + free(buffer); + SSL_shutdown(ssl); + SSL_free(ssl); + SSL_CTX_free(ctx); + closesocket(sock); + return -1; + } - char *body_start = endofhdr + 4; - size_t body_len = total_bytes - (body_start - buffer); + char *body_start = endofhdr + 4; + size_t body_len = total_bytes - (body_start - buffer); if (strstr(buffer, "Transfer-Encoding: chunked")) { size_t outlen; - *response = ProcessChunkedTransfer(body_start,body_len,&outlen); - *responselen = (long)outlen; - free(buffer); - } else { - char *copy = malloc(body_len + 1); - memcpy(copy, body_start, body_len); - copy[body_len] = '\0'; - *response = copy; - *responselen = (long)body_len; - free(buffer); - } + *response = ProcessChunkedTransfer(body_start, body_len, &outlen); + *responselen = (long)outlen; + free(buffer); + } else { + char *copy = malloc(body_len + 1); + memcpy(copy, body_start, body_len); + copy[body_len] = '\0'; + *response = copy; + *responselen = (long)body_len; + free(buffer); + } - SSL_shutdown(ssl); - SSL_free(ssl); - SSL_CTX_free(ctx); - closesocket(sock); - return 0; + SSL_shutdown(ssl); + SSL_free(ssl); + SSL_CTX_free(ctx); + closesocket(sock); + return 0; } int InitHTTP() { - SSL_library_init(); - SSL_load_error_strings(); - OpenSSL_add_all_algorithms(); - WSADATA wsaData; - WSAStartup(MAKEWORD(2,2), &wsaData); //me when macros -} -int CleanupHTTP() { - WSACleanup(); + SSL_library_init(); + SSL_load_error_strings(); + OpenSSL_add_all_algorithms(); + WSADATA wsaData; + WSAStartup(MAKEWORD(2, 2), &wsaData); // me when macros } +int CleanupHTTP() { WSACleanup(); } diff --git a/http.h b/http.h index 8d0607b..3f0c037 100755 --- a/http.h +++ b/http.h @@ -1,10 +1,26 @@ + +#include +#include +#include +// keepalive state +typedef struct { + SOCKET sock; + SSL* ssl; + SSL_CTX* ctx; + char hostname[256]; + int connected; +} HTTPConnection; void InitSockets(); int SendShortHTTPReq(const char *hostname, const char *reqtype, const char *endpoint, const char *extra_headers, const char *user_agent, const char *content_type, void *payload, unsigned long payload_size, char** response, long* responselen); - +HTTPConnection* HTTPConnect(const char* hostname); +int SendHTTPRequest(HTTPConnection* conn, const char* method, const char* endpoint, const char* extra_headers, + const char* user_agent, const char* content_type, void* payload, + unsigned long payload_size, char** response, long* responselen); +int CloseHTTPConnection(HTTPConnection* conn); static void AppendHeader(char *buf, const char *key, const char *value); int InitHTTP(); diff --git a/main.c b/main.c index 76fe7d3..3b74ce5 100755 --- a/main.c +++ b/main.c @@ -264,6 +264,15 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, HFONT BoldSysFont = CreateFontIndirect(&ncm.lfMessageFont); InitHTTP(); + /* HTTPConnection* hc = HTTPConnect("httpbin.org"); + long responselen; + char* response; + SendHTTPRequest(hc, "GET", "/get", "", user_agent, NULL, NULL, 0, &response, &responselen); + MessageBoxA(NULL,response,"HTTP Test",0); + if(responselen==strlen(response)){ + MessageBoxA(NULL,"pass","HTTP Test",0); + }*/ + DiscordHTTPConnect(); RECT rc; GetClientRect(hwnd, &rc); @@ -623,6 +632,7 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, PostQuitMessage(0); case WM_DESTROY: CleanupHTTP(); + DiscordHTTPClose(); return TRUE; break; }