summaryrefslogtreecommitdiff
path: root/lib/internal.h
blob: 2db57ecb51b135aa42f6eaf412fba42a2eb2ac77 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#ifndef YPC_INTERNAL_H_
#define YPC_INTERNAL_H_

#if defined(_WIN32) || defined(__MINGW32__) || defined(__CYGWIN__)
#define YPC_EXPORT __declspec(dllexport)
#else
#define YPC_EXPORT
#endif

#include "ypc.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <assert.h>


#if defined(_MSC_VER) || defined(__MINGW32__)
#define WINSOCK
#include <winsock2.h>
#include <ws2tcpip.h>
#define snprintf _snprintf
typedef int ssize_t;
/* We don't use close() on non-sockets on windows, so this hack should be safe. */
#define close closesocket
#define WSAEAGAIN WSAEWOULDBLOCK
#define ypc__neterrcode(n) (WSA##n)
#define ypc__neterrno WSAGetLastError()
#define ypc__neterr(n) (WSAGetLastError() == WSA##n)

#else
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/uio.h>
#include <sys/un.h>
#define ypc__neterrcode(n) (n)
#define ypc__neterrno errno
#define ypc__neterr(n) (errno == n)
#endif


#if defined(__MINGW32__)
/* MinGW header files aren't complete... */
WINSOCK_API_LINKAGE const char WSAAPI inet_pton(int af, const char *src, void *dst);
#endif


/* Wrapper for accessing struct iovec / WSABUF */
#ifdef WINSOCK
typedef WSABUF ypc_iovec;
#define ypc__iovec_buf(x) ((x).buf)
#define ypc__iovec_len(x) ((x).len)
#else
typedef struct iovec ypc_iovec;
#define ypc__iovec_buf(x) ((x).iov_base)
#define ypc__iovec_len(x) ((x).iov_len)
#endif


#ifdef YPC_LIBSODIUM
#include <sodium.h>
#else
#include "util/tweetnacl.h"
#endif


#define YPC_TCPS_MAXPACKET 4096


typedef enum {
    YPCN_CONNECTING,
    YPCN_TCPS,       /* tcps:// handshake */
    YPCN_CONNECTED,
    YPCN_DISCON
} ypc_state;


struct ypc_msg {
    /* Interior pointers, used in either the send or receive queue. */
    ypc_msg *next, *prev;
    /* Length of the message contents */
    size_t len;
    /* Size of the allocated buffer, minus the 4-byte length prefix. */
    size_t size;
    /* First four bytes are used for the length prefix. These bytes are only
     * updated when needed, the 'len' field always holds the correct length.
     */
    uint8_t *data;
};


typedef struct {
    ypc_msg *first, *last;
} ypc_queue;


typedef struct {
    size_t slen; /* including first byte */
    size_t soff;
    size_t rlen; /* excluding first byte */
    size_t roff;

    /* Our own ephemeral public/secret keys */
    uint8_t sk[32];
    uint8_t pk[32];

    /* Server permanent public/secret key. */
    uint8_t ssk[32];
    uint8_t spk[32];

    /* The crypto_box_beforenm() state used for sending and receiving. */
    uint8_t nm[32];

    uint8_t snonce[24];
    uint8_t rnonce[24];

    /* The 16 bytes before the message is used for the crypto_box() zero bytes,
     * these are not actually sent over the network. One byte before the actual
     * send[] message is also reserved for the length prefix, which IS sent
     * over the network. */
    uint8_t send[16+YPC_TCPS_MAXPACKET];
    uint8_t recv[16+YPC_TCPS_MAXPACKET];
} ypc_tcps;


struct ypc {
    int fd;
    ypc_state state;
    bool server;

    ypc_queue send;
    size_t send_off;

    ypc_queue recv;
    ypc_msg *recv_msg;
    uint32_t recv_size;
    uint8_t recv_state;

    ypc_tcps *tcps;
};


struct ypc_serv {
    int fd;
    bool secure;
    uint8_t ssk[32];
    uint8_t spk[32];
};


/* queue.c */
ypc_msg *ypc__dequeue(ypc_queue *);
void ypc__enqueue(ypc_queue *, ypc_msg *);

/* msgio.c */
int ypc__msgio_recv(ypc *, uint8_t *, size_t);
int ypc__msgio_sendbuf(ypc *, ypc_iovec *, int);
void ypc__msgio_sendlen(ypc *, size_t);

/* tcps.c */
int ypc__tcps_init(ypc *);
int ypc__tcps_recv(ypc *, uint8_t *, size_t);
int ypc__tcps_sendbuf(ypc *, ypc_iovec *, int);
void ypc__tcps_sendlen(ypc *, size_t);

/* util/errcode.c */
int ypc__errcode(int);

/* util/socket.c */
int ypc__socket(int, int, int);
/* util/serversock.c */
int ypc__serversock(int, void *, socklen_t, bool);
/* util/bin2hex.c */
void ypc__bin2hex(char *, const uint8_t *, size_t);
/* util/hex2bin.c */
int ypc__hex2bin(uint8_t *, const char *, size_t);

#endif