Skip to content

Instantly share code, notes, and snippets.

@angeloped
Created January 8, 2023 01:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save angeloped/6a086667579d46937fec1dc37810028b to your computer and use it in GitHub Desktop.
Save angeloped/6a086667579d46937fec1dc37810028b to your computer and use it in GitHub Desktop.
A truly Cross-Platform socket client written in C language.
#include <stdio.h>
// 1/8/2022
// modified version of https://github.com/ApOgEE/mingw-c-socket
// WORKS ON Linux kali 4.19.0-kali4-686-pae #1 SMP Debian 4.19.28-2kali1 (2019-03-18) i686 GNU/Linux
//////////////////////////////////////////////////////////////////////////
// CROSS-PLATFORMING A SOCKET PROGRAM
// See https://stackoverflow.com/questions/28027937/cross-platform-sockets
//////////////////////////////////////////////////////////
// The header and lib files are different
// You'll need to include different header files depending on whether you're using Windows or not:
#ifdef _WIN32
// FOR WINDOWS
/* See http://stackoverflow.com/questions/12765743/getaddrinfo-on-win32 */
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 /* Windows XP. */
#endif
/* winsock2.h was designed to replace winsock.h, not extend it. Everything that is defined in winsock.h is also defined in winsock2.h (https://stackoverflow.com/questions/9153911/) */
#include <winsock2.h>
#else
// FOR UNIX/POSIX
/* Assume that any non-Windows platform uses POSIX-style sockets instead. */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h> /* Needed for getaddrinfo() and freeaddrinfo() */
#include <unistd.h> /* Needed for close() */
#include <string.h> /* Needed to provide a declaration of memset */
#include <stdlib.h> /* Needed to provide a declaration of exit */
#endif
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
// WinSock requires initialisation and cleanup.
// The functions below illustrate how you can initialise WinSock v1.1 and clean up afterwards
int sockInit(void){
#ifdef _WIN32
WSADATA wsa_data; // winsock2.h
return WSAStartup(MAKEWORD(1,1), &wsa_data); // winsock2.h
//WSADATA wsaData; // winsock.h
//WSAStartup(MAKEWORD(2, 2), &wsaData); // winsock.h
#else
return 0;
#endif
}
int sockQuit(void){
#ifdef _WIN32
return WSACleanup();
#else
return 0;
#endif
}
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
// socket connect error variable
#ifdef _WIN32
// FOR WINDOWS
#define SOCKET_ERROR_ SOCKET_ERROR
#else
// FOR UNIX/POSIX
#define SOCKET_ERROR_ SO_ERROR
#endif
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
// Sockets are closed differently
// The function below illustrates the differences:
/* Note: For POSIX, typedef SOCKET as an int. */
//int sockClose(SOCKET sock){
int sockClose(int sock){
int status = 0;
#ifdef _WIN32
status = shutdown(sock, SD_BOTH);
if (status == 0) { status = closesocket(sock); }
#else
status = shutdown(sock, SHUT_RDWR);
if (status == 0) { status = close(sock); }
#endif
return status;
}
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
#define PORT 80
#define USERAGENT "ApOgEE MinGW Socket Client 1.0"
char *build_get_query(char *, char *);
int main(int argc, char *argv[]){
int client_socket;
char *host;
struct hostent *hent;
int iplen = 15; //XXX.XXX.XXX.XXX
struct sockaddr_in *remote;
int tmpres;
char *get;
char buf[BUFSIZ+1];
//printf("Socket client example\n");
// create tcp socket
sockInit();
client_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (client_socket < 0) {
printf("client_socket = %d\n",client_socket);
perror("Can't create TCP socket\n");
exit(1);
}
// get host ip
host = "static.licdn.com";
//printf("Host: %s\n",host);
char *ip = (char *)malloc(iplen+1);
memset(ip, 0, iplen+1);
if((hent = gethostbyname(host)) == NULL)
{
perror("Can't get IP");
exit(1);
}
ip = inet_ntoa(*(struct in_addr *)*hent->h_addr_list);
//printf("The IP: %s\n",ip);
// setup remote socket
remote = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in *));
remote->sin_family = AF_INET;
//printf("s_addr:%d\n",remote->sin_addr.s_addr);
remote->sin_addr.s_addr = inet_addr(ip);
remote->sin_port = htons(PORT);
//printf("s_addr:%d\n",remote->sin_addr.s_addr);
// have to read
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms737625(v=vs.85).aspx
// connect socket
if(connect(client_socket, (struct sockaddr *)remote, sizeof(struct sockaddr)) == SOCKET_ERROR_){
perror("Could not connect");
sockClose(client_socket); // MULTIPLATFORM
sockQuit(); // FOR WINDOWS
exit(1);
}
// prepare query
get = build_get_query(host,"/sc/h/5q92mjc5c51bjlwaj3rs9aa82");
//printf("query: \n%s\n",get);
//Send the query to the server
int sent = 0;
while(sent < strlen(get)) {
tmpres = send(client_socket, get+sent, strlen(get)-sent, 0);
if(tmpres == -1) {
perror("Can't send query");
exit(1);
}
sent += tmpres;
}
//now it is time to receive the page
memset(buf, 0, sizeof(buf));
int htmlstart = 0;
char * htmlcontent;
while((tmpres = recv(client_socket, buf, BUFSIZ, 0)) > 0) {
if(htmlstart == 0) {
/* Under certain conditions this will not work.
* If the \r\n\r\n part is splitted into two messages
* it will fail to detect the beginning of HTML content
*/
htmlcontent = strstr(buf, "\r\n\r\n");
if(htmlcontent != NULL){
htmlstart = 1;
htmlcontent += 4;
}
} else {
htmlcontent = buf;
}
if(htmlstart) {
FILE *fp;
fp = fopen("file.svg", "ab+");
fprintf(fp, htmlcontent);
//fputs(htmlcontent, fp);
fclose(fp);
// use only to show downloaded contents
//fprintf(stdout, htmlcontent);
}
memset(buf, 0, tmpres);
}
if(tmpres < 0) {
perror("Error receiving data");
}
free(get);
free(remote);
sockClose(client_socket); // MULTIPLATFORM
sockQuit(); // FOR WINDOWS
//printf("Program end");
return 0;
}
char *build_get_query(char *host, char *page){
char *query;
char *getpage = page;
char *tpl = "GET /%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: %s\r\n\r\n";
if(getpage[0] == '/'){
getpage = getpage + 1;
//fprintf(stderr,"Removing leading \"/\", converting %s to %s\n", page, getpage);
}
// -5 is to consider the %s %s %s in tpl and the ending \0
query = (char *)malloc(strlen(host)+strlen(getpage)+strlen(USERAGENT)+strlen(tpl)-5);
sprintf(query, tpl, getpage, host, USERAGENT);
return query;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment