added SOCKS library for socket I/O
This commit is contained in:
parent
1fc16cd54a
commit
816ffa2b5d
|
@ -29,6 +29,7 @@ SET(HDRS
|
|||
unicode.h
|
||||
error.h
|
||||
binding.h
|
||||
inet.h
|
||||
)
|
||||
|
||||
SET(SRCS
|
||||
|
@ -40,6 +41,7 @@ SET(SRCS
|
|||
unicode.c
|
||||
error.c
|
||||
binding.c
|
||||
inet.c
|
||||
)
|
||||
|
||||
add_executable(lci ${SRCS} ${HDRS})
|
||||
|
|
146
binding.c
146
binding.c
|
@ -1,4 +1,5 @@
|
|||
#include "binding.h"
|
||||
#include "inet.h" /* for SOCKS */
|
||||
|
||||
ValueObject *getArg(struct scopeobject *scope, char *name)
|
||||
{
|
||||
|
@ -8,6 +9,102 @@ ValueObject *getArg(struct scopeobject *scope, char *name)
|
|||
return val;
|
||||
}
|
||||
|
||||
ReturnObject *iopenWrapper(struct scopeobject *scope)
|
||||
{
|
||||
ValueObject *arg1 = getArg(scope, "addr");
|
||||
ValueObject *arg2 = getArg(scope, "port");
|
||||
char *addr = getString(arg1);
|
||||
int port = getInteger(arg2);
|
||||
|
||||
inet_host_t *h = malloc(sizeof(inet_host_t));
|
||||
inet_open(h, IN_PROT_TCP, addr, port);
|
||||
|
||||
ValueObject *ret = createBlobValueObject(h);
|
||||
return createReturnObject(RT_RETURN, ret);
|
||||
}
|
||||
|
||||
ReturnObject *ilookupWrapper(struct scopeobject *scope)
|
||||
{
|
||||
ValueObject *arg1 = getArg(scope, "addr");
|
||||
char *addr = getString(arg1);
|
||||
|
||||
char *h = inet_lookup(addr);
|
||||
|
||||
ValueObject *ret = createStringValueObject(h);
|
||||
return createReturnObject(RT_RETURN, ret);
|
||||
}
|
||||
|
||||
ReturnObject *iacceptWrapper(struct scopeobject *scope)
|
||||
{
|
||||
ValueObject *arg1 = getArg(scope, "local");
|
||||
inet_host_t *host = (inet_host_t *)getBlob(arg1);
|
||||
|
||||
inet_host_t *h = malloc(sizeof(inet_host_t));
|
||||
inet_accept(h, host);
|
||||
|
||||
ValueObject *ret = createBlobValueObject(h);
|
||||
return createReturnObject(RT_RETURN, ret);
|
||||
}
|
||||
|
||||
ReturnObject *iconnectWrapper(struct scopeobject *scope)
|
||||
{
|
||||
ValueObject *arg1 = getArg(scope, "local");
|
||||
ValueObject *arg2 = getArg(scope, "addr");
|
||||
ValueObject *arg3 = getArg(scope, "port");
|
||||
inet_host_t *host = (inet_host_t *)getBlob(arg1);
|
||||
char *addr = getString(arg2);
|
||||
int port = getInteger(arg3);
|
||||
|
||||
inet_host_t *h = malloc(sizeof(inet_host_t));
|
||||
inet_setup(h, IN_PROT_TCP, addr, port);
|
||||
inet_connect(host, h);
|
||||
|
||||
ValueObject *ret = createBlobValueObject(h);
|
||||
return createReturnObject(RT_RETURN, ret);
|
||||
}
|
||||
|
||||
ReturnObject *icloseWrapper(struct scopeobject *scope)
|
||||
{
|
||||
ValueObject *arg1 = getArg(scope, "local");
|
||||
inet_host_t *host = (inet_host_t *)getBlob(arg1);
|
||||
|
||||
inet_close(host);
|
||||
|
||||
ValueObject *ret = createBlobValueObject(host);
|
||||
return createReturnObject(RT_RETURN, ret);
|
||||
}
|
||||
|
||||
ReturnObject *isendWrapper(struct scopeobject *scope)
|
||||
{
|
||||
ValueObject *arg1 = getArg(scope, "local");
|
||||
ValueObject *arg2 = getArg(scope, "remote");
|
||||
ValueObject *arg3 = getArg(scope, "data");
|
||||
inet_host_t *local = (inet_host_t *)getBlob(arg1);
|
||||
inet_host_t *remote = (inet_host_t *)getBlob(arg2);
|
||||
char *data = getString(arg3);
|
||||
|
||||
int n = inet_send(local, remote, data, strlen(data));
|
||||
|
||||
ValueObject *ret = createIntegerValueObject(n);
|
||||
return createReturnObject(RT_RETURN, ret);
|
||||
}
|
||||
|
||||
ReturnObject *ireceiveWrapper(struct scopeobject *scope)
|
||||
{
|
||||
ValueObject *arg1 = getArg(scope, "local");
|
||||
ValueObject *arg2 = getArg(scope, "remote");
|
||||
ValueObject *arg3 = getArg(scope, "amount");
|
||||
inet_host_t *local = (inet_host_t *)getBlob(arg1);
|
||||
inet_host_t *remote = (inet_host_t *)getBlob(arg2);
|
||||
int amount = getInteger(arg3);
|
||||
|
||||
char *data = malloc(sizeof(char) * amount);
|
||||
inet_receive(remote, local, data, amount, -1);
|
||||
|
||||
ValueObject *ret = createStringValueObject(data);
|
||||
return createReturnObject(RT_RETURN, ret);
|
||||
}
|
||||
|
||||
ReturnObject *fopenWrapper(struct scopeobject *scope)
|
||||
{
|
||||
ValueObject *arg1 = getArg(scope, "filename");
|
||||
|
@ -58,6 +155,16 @@ ReturnObject *fcloseWrapper(struct scopeobject *scope)
|
|||
return createReturnObject(RT_DEFAULT, NULL);
|
||||
}
|
||||
|
||||
ReturnObject *rewindWrapper(struct scopeobject *scope)
|
||||
{
|
||||
ValueObject *arg1 = getArg(scope, "file");
|
||||
FILE *file = (FILE *)getBlob(arg1);
|
||||
|
||||
rewind(file);
|
||||
|
||||
return createReturnObject(RT_DEFAULT, NULL);
|
||||
}
|
||||
|
||||
ReturnObject *strlenWrapper(struct scopeobject *scope)
|
||||
{
|
||||
ValueObject *arg1 = getArg(scope, "string");
|
||||
|
@ -100,10 +207,11 @@ void loadLibrary(ScopeObject *scope, IdentifierNode *target)
|
|||
lib = createScopeObject(scope);
|
||||
if (!lib) goto loadLibraryAbort;
|
||||
|
||||
loadBinding(lib, "FOPENIN", "filename mode", &fopenWrapper);
|
||||
loadBinding(lib, "FREADIN", "file length", &freadWrapper);
|
||||
loadBinding(lib, "FWRITIN", "file data", &fwriteWrapper);
|
||||
loadBinding(lib, "FCLOSIN", "file", &fcloseWrapper);
|
||||
loadBinding(lib, "OPEN", "filename mode", &fopenWrapper);
|
||||
loadBinding(lib, "LUK", "file length", &freadWrapper);
|
||||
loadBinding(lib, "SCRIBBEL", "file data", &fwriteWrapper);
|
||||
loadBinding(lib, "AGEIN", "file", &rewindWrapper);
|
||||
loadBinding(lib, "CLOSE", "file", &fcloseWrapper);
|
||||
|
||||
id = createIdentifierNode(IT_DIRECT, (void *)copyString("STDIO"), NULL, NULL, 0);
|
||||
if (!id) goto loadLibraryAbort;
|
||||
|
@ -116,13 +224,35 @@ void loadLibrary(ScopeObject *scope, IdentifierNode *target)
|
|||
|
||||
if (!updateScopeValue(scope, scope, id, val)) goto loadLibraryAbort;
|
||||
deleteIdentifierNode(id);
|
||||
}
|
||||
else if (!strcmp(name, "STRING")) {
|
||||
} else if (!strcmp(name, "SOCKS")) {
|
||||
lib = createScopeObject(scope);
|
||||
if (!lib) goto loadLibraryAbort;
|
||||
|
||||
loadBinding(lib, "STRLENIN", "string", &strlenWrapper);
|
||||
loadBinding(lib, "STRATIN", "string position", &stratWrapper);
|
||||
loadBinding(lib, "RESOLV", "addr", &ilookupWrapper);
|
||||
loadBinding(lib, "BIND", "addr port", &iopenWrapper);
|
||||
loadBinding(lib, "LISTN", "local timeout", &iacceptWrapper);
|
||||
loadBinding(lib, "KONN", "local addr port", &iconnectWrapper);
|
||||
loadBinding(lib, "CLOSE", "local", &icloseWrapper);
|
||||
loadBinding(lib, "PUT", "local remote data", &isendWrapper);
|
||||
loadBinding(lib, "GET", "local remote amount", &ireceiveWrapper);
|
||||
|
||||
id = createIdentifierNode(IT_DIRECT, (void *)copyString("SOCKS"), NULL, NULL, 0);
|
||||
if (!id) goto loadLibraryAbort;
|
||||
|
||||
if (!createScopeValue(scope, scope, id)) goto loadLibraryAbort;
|
||||
|
||||
val = createArrayValueObject(lib);
|
||||
if (!val) goto loadLibraryAbort;
|
||||
lib = NULL;
|
||||
|
||||
if (!updateScopeValue(scope, scope, id, val)) goto loadLibraryAbort;
|
||||
deleteIdentifierNode(id);
|
||||
} else if (!strcmp(name, "STRING")) {
|
||||
lib = createScopeObject(scope);
|
||||
if (!lib) goto loadLibraryAbort;
|
||||
|
||||
loadBinding(lib, "LEN", "string", &strlenWrapper);
|
||||
loadBinding(lib, "AT", "string position", &stratWrapper);
|
||||
|
||||
id = createIdentifierNode(IT_DIRECT, (void *)copyString("STRING"), NULL, NULL, 0);
|
||||
if (!id) goto loadLibraryAbort;
|
||||
|
|
|
@ -0,0 +1,304 @@
|
|||
#include "inet.h"
|
||||
|
||||
// inet_setup (TCP:client / UDP:client)
|
||||
//
|
||||
// Sets up an inet_host structure.
|
||||
void
|
||||
inet_setup(inet_host_t *host,
|
||||
int protocol,
|
||||
const char *addr,
|
||||
unsigned short port)
|
||||
{
|
||||
// Set up our inet_host structure
|
||||
host->protocol = protocol;
|
||||
|
||||
// Set up our sockaddr_in structure
|
||||
host->addr.sin_family = AF_INET;
|
||||
host->addr.sin_port = htons(port);
|
||||
host->addr.sin_addr.s_addr =
|
||||
(addr == IN_ADDR_ANY ? IN_ADDR_ANY : inet_addr(addr));
|
||||
memset(host->addr.sin_zero, 0, sizeof(host->addr.sin_zero));
|
||||
}
|
||||
|
||||
// inet_open (TCP / UDP)
|
||||
//
|
||||
// Prepares `host' for transmission.
|
||||
//
|
||||
// `protocol' specifies the protocol to use for the transmission and is either
|
||||
// `IN_PROT_TCP' or `IN_PROT_UDP'.
|
||||
//
|
||||
// `addr' is the IP address the host session structure will use: either a string
|
||||
// of the form `X.X.X.X', where each `X' is the textual representation of a
|
||||
// number in the range 0 to 255, or `IN_ADDR_ANY' to specify the current host's
|
||||
// IP address.
|
||||
//
|
||||
// `port' is the port number to bind to on the host machine. Specifying
|
||||
// IN_PORT_ANY attempts to use any available port assigned by the kernel. Use
|
||||
// this option when the port your host structure is bound to does not matter.
|
||||
//
|
||||
// Returns one of:
|
||||
// 0 Success.
|
||||
// -EIN_SOCK Error acquiring socket file descriptor.
|
||||
// -EIN_BIND Error binding socket to port.
|
||||
int
|
||||
inet_open(inet_host_t *host,
|
||||
int protocol,
|
||||
const char *addr,
|
||||
unsigned short port)
|
||||
{
|
||||
// If we are not able to get a socket, fail with a socket error
|
||||
host->fd = socket(PF_INET, protocol, 0);
|
||||
if (host->fd < 0) {
|
||||
perror("Error acquiring socket file descriptor!\n");
|
||||
return -EIN_SOCK;
|
||||
}
|
||||
|
||||
// Set up our sockaddr_in structure
|
||||
inet_setup(host, protocol, addr, port);
|
||||
|
||||
// If we are not able to bind to a port, fail with a bind error
|
||||
if (bind(host->fd, (struct sockaddr *)&(host->addr),
|
||||
sizeof(host->addr)) < 0) {
|
||||
perror("Error acquiring socket file descriptor!\n");
|
||||
return -EIN_BIND;
|
||||
}
|
||||
|
||||
// Set up our host protocol
|
||||
host->protocol = protocol;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// inet_accept (TCP:server)
|
||||
//
|
||||
// Accepts an incoming connection from the `remote' host to the `local' host.
|
||||
//
|
||||
// Returns one of:
|
||||
// 0 Success.
|
||||
// -EIN_PROT Incorrect protocol.
|
||||
// -EIN_LSTN Error listening.
|
||||
// -EIN_ACPT Error accepting connection.
|
||||
int
|
||||
inet_accept(inet_host_t *remote,
|
||||
inet_host_t *local)
|
||||
{
|
||||
socklen_t len = sizeof(remote->addr);
|
||||
|
||||
// Make sure we only accept TCP sessions
|
||||
if (local->protocol != IN_PROT_TCP) {
|
||||
fprintf(stderr, "Error accepting from non-TCP protocol!\n");
|
||||
return -EIN_PROT;
|
||||
}
|
||||
|
||||
// Listen for an acceptable connection
|
||||
if (listen(local->fd, IN_BACKLOG) < 0) {
|
||||
perror("Error encountered while listening!\n");
|
||||
return -EIN_LSTN;
|
||||
}
|
||||
|
||||
// Accept the connection
|
||||
remote->fd = accept(local->fd, (struct sockaddr *)&(remote->addr), &len);
|
||||
if (remote->fd < 0) {
|
||||
perror("Error accepting connection!\n");
|
||||
return -EIN_ACPT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// inet_connect (TCP:client)
|
||||
//
|
||||
// Connects the `local' host to the `remote' host.
|
||||
//
|
||||
// Returns one of:
|
||||
// 0 Success.
|
||||
// -EIN_PROT Incorrect protocol.
|
||||
// -EIN_CONN Error connecting to port.
|
||||
int
|
||||
inet_connect(inet_host_t *local,
|
||||
inet_host_t *remote)
|
||||
{
|
||||
// Make sure we only connect TCP sessions
|
||||
if (local->protocol != IN_PROT_TCP) {
|
||||
fprintf(stderr, "Error accepting from non-TCP protocol!\n");
|
||||
return -EIN_PROT;
|
||||
}
|
||||
|
||||
// Connect to remote host
|
||||
if (connect(local->fd, (struct sockaddr *)&(remote->addr), sizeof(remote->addr)) < 0) {
|
||||
perror("Error connecting to remote host!\n");
|
||||
return -EIN_CONN;
|
||||
}
|
||||
|
||||
// Link `local->fd' and `remote->fd' on the client because `inet_send' always
|
||||
// sends data through `remote->fd' for TCP connections (this makes sense
|
||||
// intuitively, as one would send data *to* a remote address). However, a TCP
|
||||
// client (which would be the only host to call this function) always
|
||||
// communicates through it's `local->fd' and leaves `remote->fd' unused so we
|
||||
// may safely repurpose it for the sake of continuity.
|
||||
remote->fd = local->fd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// inet_receive (TCP / UDP)
|
||||
//
|
||||
// Receives a `len' bytes sent from `remote' to `local' and stores them in
|
||||
// `data'. If no message is received within `timeout' seconds, -EIN_TIME is
|
||||
// returned.
|
||||
//
|
||||
// Setting `timeout' to 0 causes the function to return immediately if there is
|
||||
// no data to receive and setting `timeout' to -1 causes the function to block
|
||||
// until data is ready to be received.
|
||||
//
|
||||
// Returns one of:
|
||||
// Number of bytes received Success.
|
||||
// -EIN_TIME Timeout.
|
||||
// -EIN_RECV Error receiving data.
|
||||
int
|
||||
inet_receive(inet_host_t *remote,
|
||||
inet_host_t *local,
|
||||
void *data,
|
||||
int len,
|
||||
int timeout)
|
||||
{
|
||||
fd_set fds;
|
||||
struct timeval time;
|
||||
int size;
|
||||
|
||||
// Set the timeout interval
|
||||
time.tv_sec = timeout;
|
||||
time.tv_usec = 0;
|
||||
|
||||
// Initialize the file descriptor set
|
||||
FD_ZERO(&fds);
|
||||
|
||||
// Depending on the protocol, receive data
|
||||
switch (local->protocol) {
|
||||
case IN_PROT_TCP:
|
||||
FD_SET(remote->fd, &fds);
|
||||
// Block for a specified amount of time
|
||||
if (timeout != -1)
|
||||
select(remote->fd + 1, &fds, NULL, NULL, &time);
|
||||
else
|
||||
select(remote->fd + 1, &fds, NULL, NULL, NULL);
|
||||
if (FD_ISSET(remote->fd, &fds)) {
|
||||
size = recv(remote->fd, data, len, 0);
|
||||
if (size < 0) {
|
||||
perror("Error receiving data!\n");
|
||||
return -EIN_RECV;
|
||||
}
|
||||
}
|
||||
else
|
||||
return -EIN_TIME;
|
||||
break;
|
||||
case IN_PROT_UDP: {
|
||||
socklen_t n = sizeof(remote->addr);
|
||||
FD_SET(local->fd, &fds);
|
||||
// Block for a specified amount of time
|
||||
if (timeout != -1)
|
||||
select(local->fd + 1, &fds, NULL, NULL, &time);
|
||||
else
|
||||
select(local->fd + 1, &fds, NULL, NULL, NULL);
|
||||
if (FD_ISSET(local->fd, &fds)) {
|
||||
size = recvfrom(local->fd, data, len, 0,
|
||||
(struct sockaddr *)&(remote->addr), &n);
|
||||
if (size < 0) {
|
||||
perror("Error receiving data!\n");
|
||||
return -EIN_RECV;
|
||||
}
|
||||
}
|
||||
else
|
||||
return -EIN_TIME;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
// inet_send (TCP / UDP)
|
||||
//
|
||||
// Sends `len' bytes of `data' from `local' to `remote'.
|
||||
//
|
||||
// Returns one of:
|
||||
// Number of bytes sent Success.
|
||||
// -EIN_SEND Error sending data.
|
||||
int
|
||||
inet_send(inet_host_t *local,
|
||||
inet_host_t *remote,
|
||||
void *data,
|
||||
int len)
|
||||
{
|
||||
int size;
|
||||
|
||||
// Depending on the protocol, send data
|
||||
switch (local->protocol) {
|
||||
case IN_PROT_TCP:
|
||||
size = send(remote->fd, data, len, 0);
|
||||
if (size < 0) {
|
||||
perror("Error sending data!\n");
|
||||
return -EIN_SEND;
|
||||
}
|
||||
break;
|
||||
case IN_PROT_UDP: {
|
||||
size = sendto(local->fd, data, len, 0,
|
||||
(struct sockaddr *)&(remote->addr), sizeof(remote->addr));
|
||||
if (size < 0) {
|
||||
perror("Error sending data!\n");
|
||||
return -EIN_SEND;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
// inet_close (TCP / UDP)
|
||||
//
|
||||
// Closes an inet connection.
|
||||
//
|
||||
// Returns one of:
|
||||
// 0 Success.
|
||||
// -1 Invalid `host' pointer.
|
||||
int
|
||||
inet_close(inet_host_t *host)
|
||||
{
|
||||
// Sanity check
|
||||
if (!host) return -1;
|
||||
|
||||
// Close the file descriptor
|
||||
if (host->fd) close(host->fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// inet_lookup
|
||||
//
|
||||
// Looks up information by resolving a DNS name and returns a pointer to the
|
||||
// resolved IP address.
|
||||
//
|
||||
// Returns one of:
|
||||
// 0 Unable to resolve name.
|
||||
// Pointer to resolved IP address Must be freed by caller.
|
||||
char *
|
||||
inet_lookup(const char *name)
|
||||
{
|
||||
char *hostname;
|
||||
char *temp;
|
||||
struct hostent *ent;
|
||||
|
||||
// If unable to get host by name, quit with lookup error
|
||||
if (!(ent = gethostbyname(name))) {
|
||||
herror("gethostbyname");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Copy the looked up name
|
||||
temp = inet_ntoa(*((struct in_addr *)ent->h_addr));
|
||||
hostname = malloc(sizeof(char) * (strlen(temp) + 1));
|
||||
strcpy(hostname, temp);
|
||||
|
||||
return hostname;
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
// inet.h
|
||||
// A library for simplifying networked communication.
|
||||
// 2008-4-27
|
||||
//
|
||||
// MAINTAINER
|
||||
//
|
||||
// Justin J. Meza <justin dot meza at gmail dot com>
|
||||
//
|
||||
// LICENSE
|
||||
//
|
||||
// You are free to use, modify, and re-distribute this software provided
|
||||
// that you make any modifications publicly available. Additionally, this
|
||||
// software is provided without any warranty; use of this software is at the
|
||||
// user's own risk. The author disclaims any liability for malfunctions as a
|
||||
// result of this software or any derivative works produced with it.
|
||||
//
|
||||
// Please report and bugs, fixes, and improvements to the maintainer.
|
||||
//
|
||||
// This library allows two `host's (specifically, two processes) to connect and
|
||||
// exchange data in a session using either TCP or UDP.
|
||||
//
|
||||
// The following two diagrams list the general order of function calls required
|
||||
// to handle a session for TCP and UDP. The order of function calls in `SETUP'
|
||||
// must be strictly followed; `TRANSMISSION' and `TEARDOWN' function calls may
|
||||
// be done in any order and some examples are listed.
|
||||
//
|
||||
// Functions are labeled in the form ([TCP]:[client|server] /
|
||||
// [UDP]:[client|server]) to denote whether the function is meant to be used by
|
||||
// TCP, UDP, or either connection type and furthermore whether only clients,
|
||||
// servers, or either are meant to call the function.
|
||||
//
|
||||
// +===========================================+
|
||||
// | TCP |
|
||||
// +=====================+=====================+
|
||||
// | SERVER | CLIENT |
|
||||
// +---------------------+---------------------+
|
||||
// | inet_open | inet_open |\ \
|
||||
// | inet_accept | inet_setup | | SETUP |
|
||||
// | | inet_connect |/ |
|
||||
// | | | |
|
||||
// | inet_receive | inet_send |\ TRANSMISSION > SESSION
|
||||
// | inet_send | inet_receive |/ |
|
||||
// | | | |
|
||||
// | inet_close(local) | inet_close(local) |\ TEARDOWN |
|
||||
// | inet_close(remote) | |/ /
|
||||
// +---------------------+---------------------+
|
||||
//
|
||||
// +===========================================+
|
||||
// | UDP |
|
||||
// +=====================+=====================+
|
||||
// | SERVER | CLIENT |
|
||||
// +---------------------+---------------------+
|
||||
// | inet_open | inet_open |\ SETUP \
|
||||
// | | inet_setup |/ |
|
||||
// | | | |
|
||||
// | inet_receive | inet_send |\ TRANSMISSION > SESSION
|
||||
// | inet_send | inet_receive |/ |
|
||||
// | | | |
|
||||
// | inet_close | inet_close |> TEARDOWN /
|
||||
// +---------------------+---------------------+
|
||||
|
||||
#ifndef __INET_H__
|
||||
#define __INET_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define IN_PORT_ANY 0
|
||||
#define IN_ADDR_ANY INADDR_ANY
|
||||
|
||||
#define IN_PROT_TCP SOCK_STREAM
|
||||
#define IN_PROT_UDP SOCK_DGRAM
|
||||
|
||||
#define IN_BACKLOG 10 // Number of simultaneous incoming connections to allow
|
||||
#define IN_HOSTLEN 64 //
|
||||
|
||||
// Set up our error codes
|
||||
typedef enum err_code {
|
||||
EIN_SOCK = 2, // Error acquiring socket file descriptor
|
||||
EIN_BIND, // Error binding socket to port
|
||||
EIN_CONN, // Error connecting to port
|
||||
EIN_PROT, // Incorrect protocol
|
||||
EIN_LSTN, // Error listening
|
||||
EIN_ACPT, // Error accepting connection
|
||||
EIN_SEND, // Error sending data
|
||||
EIN_RECV, // Error receiving data
|
||||
EIN_TIME, // Timeout
|
||||
} err_code_t;
|
||||
|
||||
// Structure representing an internet host
|
||||
typedef struct inet_host {
|
||||
int fd;
|
||||
int protocol;
|
||||
struct sockaddr_in addr;
|
||||
} inet_host_t;
|
||||
|
||||
void inet_setup(inet_host_t *, int, const char *, unsigned short);
|
||||
int inet_open(inet_host_t *, int, const char *, unsigned short);
|
||||
int inet_accept(inet_host_t *, inet_host_t *);
|
||||
int inet_connect(inet_host_t *, inet_host_t *);
|
||||
int inet_receive(inet_host_t *, inet_host_t *, void *, int, int);
|
||||
int inet_send(inet_host_t *, inet_host_t *, void *, int);
|
||||
int inet_close(inet_host_t *);
|
||||
char *inet_lookup(const char *);
|
||||
|
||||
#endif // __INET_H__
|
|
@ -0,0 +1,6 @@
|
|||
HAI 1.4
|
||||
CAN HAS SOCKS?
|
||||
I HAS A addr
|
||||
addr R I IZ SOCKS'Z RESOLV YR "localhost" MKAY
|
||||
VISIBLE addr
|
||||
KTHXBYE
|
|
@ -0,0 +1 @@
|
|||
127.0.0.1
|
|
@ -0,0 +1,8 @@
|
|||
HAI 1.4
|
||||
CAN HAS SOCKS?
|
||||
I HAS A sock
|
||||
I HAS A conn
|
||||
sock R I IZ SOCKS'Z BIND YR "127.0.0.1" AN YR 13337 MKAY
|
||||
I IZ SOCKS'Z CLOSE YR sock MKAY
|
||||
VISIBLE "done"
|
||||
KTHXBYE
|
|
@ -0,0 +1 @@
|
|||
done
|
|
@ -0,0 +1,11 @@
|
|||
HAI 1.4
|
||||
CAN HAS SOCKS?
|
||||
I HAS A sock
|
||||
I HAS A conn
|
||||
sock R I IZ SOCKS'Z BIND YR "127.0.0.1" AN YR 13337 MKAY
|
||||
conn R I IZ SOCKS'Z LISTN YR sock MKAY
|
||||
I HAS A cmd
|
||||
cmd R I IZ SOCKS'Z GET YR sock AN YR conn AN YR 10 MKAY
|
||||
VISIBLE "CMD IZ " AN cmd
|
||||
BTW $ cat "HAI" | nc 127.0.0.1 13337
|
||||
KTHXBYE
|
Loading…
Reference in New Issue