Extract (and abstract) socket stuff to its own module
This commit is contained in:
16
binding.gyp
16
binding.gyp
@@ -4,7 +4,21 @@
|
||||
'target_name': 'desktop-trampoline',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'src/desktop-trampoline.c'
|
||||
'src/desktop-trampoline.c',
|
||||
'src/socket.c'
|
||||
],
|
||||
'include_dirs': [
|
||||
'include'
|
||||
],
|
||||
"xcode_settings": {
|
||||
'OTHER_CFLAGS': [
|
||||
'-Wall',
|
||||
'-Werror'
|
||||
],
|
||||
},
|
||||
'cflags!': [
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
|
||||
40
include/socket.h
Normal file
40
include/socket.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifdef WINDOWS
|
||||
#include <winsock.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// There are some types missing to make everything Just Work™ in all platforms
|
||||
#ifdef WINDOWS
|
||||
#define ssize_t long
|
||||
#else
|
||||
#define SOCKET int
|
||||
#define INVALID_SOCKET -1
|
||||
#endif
|
||||
|
||||
/** Initializes anything required before working with sockets. */
|
||||
int initializeNetwork(void);
|
||||
|
||||
/** Frees resources initialized by `initializeNetwork`. */
|
||||
void terminateNetwork(void);
|
||||
|
||||
/** Creates a TCP socket and returns its handler. */
|
||||
SOCKET openSocket(void);
|
||||
|
||||
/** Closes an open socket. */
|
||||
void closeSocket(SOCKET socket);
|
||||
|
||||
/** Connects to a given port using a socket. */
|
||||
int connectSocket(SOCKET socket, unsigned short port);
|
||||
|
||||
/** Writes data into a socket. */
|
||||
int writeSocket(SOCKET socket, const void *buffer, size_t length);
|
||||
|
||||
/** Reads data from a socket. */
|
||||
int readSocket(SOCKET socket, void *buffer, size_t length);
|
||||
|
||||
/** Prints socket-related errors to stderr. */
|
||||
void printSocketError(char *fmt, ...);
|
||||
@@ -1,59 +1,15 @@
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef WINDOWS
|
||||
|
||||
#include <winsock.h>
|
||||
|
||||
#define ssize_t long
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define SOCKET int
|
||||
#define INVALID_SOCKET -1
|
||||
|
||||
#endif
|
||||
#include "socket.h"
|
||||
|
||||
#define BUFFER_LENGTH 4096
|
||||
|
||||
int safeSend(SOCKET socket, const void *buffer, size_t length, int flags) {
|
||||
return (send(socket, buffer, length, flags) < (ssize_t)length ? -1 : 0);
|
||||
}
|
||||
|
||||
void closeSocket(SOCKET socket) {
|
||||
#ifdef WINDOWS
|
||||
closesocket(socket);
|
||||
#else
|
||||
close(socket);
|
||||
#endif
|
||||
}
|
||||
|
||||
void printSocketError(char *fmt, ...)
|
||||
{
|
||||
char formatted_string[4096];
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, fmt);
|
||||
vsprintf(formatted_string, fmt, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
#ifdef WINDOWS
|
||||
fprintf(stderr, "%s: %ld\n", formatted_string, WSAGetLastError());
|
||||
#else
|
||||
fprintf(stderr, "%s (%d): %s\n", formatted_string, errno, strerror(errno));
|
||||
#endif
|
||||
}
|
||||
|
||||
#define SEND_STRING_OR_EXIT(socket, dataName, dataString) \
|
||||
if (safeSend(socket, dataString, strlen(dataString) + 1, 0) != 0) { \
|
||||
#define WRITE_STRING_OR_EXIT(dataName, dataString) \
|
||||
if (writeSocket(socket, dataString, strlen(dataString) + 1) != 0) { \
|
||||
printSocketError("ERROR: Couldn't send " dataName); \
|
||||
return 1; \
|
||||
}
|
||||
@@ -75,21 +31,16 @@ int runTrampolineClient(SOCKET *outSocket, int argc, char **argv, char **envp) {
|
||||
|
||||
unsigned short desktopPort = atoi(desktopPortString);
|
||||
|
||||
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
SOCKET socket = openSocket();
|
||||
|
||||
if (s == INVALID_SOCKET) {
|
||||
if (socket == INVALID_SOCKET) {
|
||||
printSocketError("ERROR: Couldn't create TCP socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
*outSocket = s;
|
||||
*outSocket = socket;
|
||||
|
||||
struct sockaddr_in remote = {0};
|
||||
remote.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
remote.sin_family = AF_INET;
|
||||
remote.sin_port = htons(desktopPort);
|
||||
|
||||
if (connect(s, (struct sockaddr *)&remote, sizeof(struct sockaddr_in)) != 0) {
|
||||
if (connectSocket(socket, desktopPort) != 0) {
|
||||
printSocketError("ERROR: Couldn't connect to 127.0.0.1:%d", desktopPort);
|
||||
return 1;
|
||||
}
|
||||
@@ -97,11 +48,11 @@ int runTrampolineClient(SOCKET *outSocket, int argc, char **argv, char **envp) {
|
||||
// Send the number of arguments
|
||||
char argcString[33];
|
||||
snprintf(argcString, 33, "%d", argc);
|
||||
SEND_STRING_OR_EXIT(s, "number of arguments", argcString);
|
||||
WRITE_STRING_OR_EXIT("number of arguments", argcString);
|
||||
|
||||
// Send each argument separated by \0
|
||||
for (int idx = 0; idx < argc; idx++) {
|
||||
SEND_STRING_OR_EXIT(s, "argument", argv[idx]);
|
||||
WRITE_STRING_OR_EXIT("argument", argv[idx]);
|
||||
}
|
||||
|
||||
// Get the number of environment variables
|
||||
@@ -113,12 +64,12 @@ int runTrampolineClient(SOCKET *outSocket, int argc, char **argv, char **envp) {
|
||||
// Send the number of environment variables
|
||||
char envcString[33];
|
||||
snprintf(envcString, 33, "%d", envc);
|
||||
SEND_STRING_OR_EXIT(s, "number of environment variables", envcString);
|
||||
WRITE_STRING_OR_EXIT("number of environment variables", envcString);
|
||||
|
||||
// Send the environment variables
|
||||
for (char **env = envp; *env != 0; env++) {
|
||||
char *thisEnv = *env;
|
||||
SEND_STRING_OR_EXIT(s, "environment variable", thisEnv);
|
||||
WRITE_STRING_OR_EXIT("environment variable", thisEnv);
|
||||
}
|
||||
|
||||
// TODO: send stdin stuff?
|
||||
@@ -129,7 +80,7 @@ int runTrampolineClient(SOCKET *outSocket, int argc, char **argv, char **envp) {
|
||||
|
||||
// Read output from server
|
||||
do {
|
||||
bytesRead = recv(s, buffer + totalBytesRead, BUFFER_LENGTH - totalBytesRead, 0);
|
||||
bytesRead = readSocket(socket, buffer + totalBytesRead, BUFFER_LENGTH - totalBytesRead);
|
||||
|
||||
if (bytesRead == -1) {
|
||||
printSocketError("ERROR: Error reading from socket");
|
||||
@@ -148,15 +99,9 @@ int runTrampolineClient(SOCKET *outSocket, int argc, char **argv, char **envp) {
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp) {
|
||||
#ifdef WINDOWS
|
||||
// Initialize Winsock
|
||||
WSADATA wsaData;
|
||||
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
|
||||
if (iResult != NO_ERROR) {
|
||||
fprintf(stderr, "ERROR: WSAStartup failed: %d\n", iResult);
|
||||
if (initializeNetwork() != 0) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
SOCKET socket = INVALID_SOCKET;
|
||||
int result = runTrampolineClient(&socket, argc, argv, envp);
|
||||
@@ -166,9 +111,7 @@ int main(int argc, char **argv, char **envp) {
|
||||
closeSocket(socket);
|
||||
}
|
||||
|
||||
#ifdef WINDOWS
|
||||
WSACleanup();
|
||||
#endif
|
||||
terminateNetwork();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
72
src/socket.c
Normal file
72
src/socket.c
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "socket.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int initializeNetwork(void) {
|
||||
#ifdef WINDOWS
|
||||
// Initialize Winsock
|
||||
WSADATA wsaData;
|
||||
int result = WSAStartup(MAKEWORD(2,2), &wsaData);
|
||||
if (result != NO_ERROR) {
|
||||
fprintf(stderr, "ERROR: WSAStartup failed: %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void terminateNetwork(void) {
|
||||
#ifdef WINDOWS
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
SOCKET openSocket(void) {
|
||||
return socket(AF_INET, SOCK_STREAM, 0);
|
||||
}
|
||||
|
||||
void closeSocket(SOCKET socket) {
|
||||
#ifdef WINDOWS
|
||||
closesocket(socket);
|
||||
#else
|
||||
close(socket);
|
||||
#endif
|
||||
}
|
||||
|
||||
int connectSocket(SOCKET socket, unsigned short port) {
|
||||
struct sockaddr_in remote = {0};
|
||||
remote.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
remote.sin_family = AF_INET;
|
||||
remote.sin_port = htons(port);
|
||||
|
||||
return connect(socket, (struct sockaddr *)&remote, sizeof(struct sockaddr_in));
|
||||
}
|
||||
|
||||
int writeSocket(SOCKET socket, const void *buffer, size_t length) {
|
||||
return (send(socket, buffer, length, 0) < (ssize_t)length ? -1 : 0);
|
||||
}
|
||||
|
||||
int readSocket(SOCKET socket, void *buffer, size_t length) {
|
||||
return recv(socket, buffer, length, 0);
|
||||
}
|
||||
|
||||
void printSocketError(char *fmt, ...)
|
||||
{
|
||||
char formatted_string[4096];
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, fmt);
|
||||
vsprintf(formatted_string, fmt, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
#ifdef WINDOWS
|
||||
fprintf(stderr, "%s: %ld\n", formatted_string, WSAGetLastError());
|
||||
#else
|
||||
fprintf(stderr, "%s (%d): %s\n", formatted_string, errno, strerror(errno));
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user