2022-01-24 03:28:16 +00:00
|
|
|
#include "lerror.h"
|
|
|
|
#include "lmem.h"
|
|
|
|
#include "lpeer.h"
|
|
|
|
|
2022-01-31 01:10:10 +00:00
|
|
|
struct sLaika_peer *laikaS_newPeer(PeerPktHandler *handlers, LAIKAPKT_SIZE *pktSizeTable, struct sLaika_pollList *pList, void *uData) {
|
2022-01-24 03:28:16 +00:00
|
|
|
struct sLaika_peer *peer = laikaM_malloc(sizeof(struct sLaika_peer));
|
|
|
|
|
|
|
|
laikaS_initSocket(&peer->sock);
|
2022-01-31 01:10:10 +00:00
|
|
|
peer->handlers = handlers;
|
2022-01-24 03:28:16 +00:00
|
|
|
peer->pktSizeTable = pktSizeTable;
|
2022-01-25 02:57:54 +00:00
|
|
|
peer->pList = pList;
|
|
|
|
peer->uData = uData;
|
2022-01-24 03:28:16 +00:00
|
|
|
peer->pktSize = 0;
|
2022-01-31 01:22:02 +00:00
|
|
|
peer->type = PEER_UNVERIFIED;
|
2022-01-24 03:28:16 +00:00
|
|
|
peer->pktID = LAIKAPKT_MAXNONE;
|
|
|
|
peer->setPollOut = false;
|
2022-02-04 02:51:32 +00:00
|
|
|
peer->outStart = -1;
|
|
|
|
peer->inStart = -1;
|
|
|
|
peer->useSecure = false;
|
2022-01-24 03:28:16 +00:00
|
|
|
return peer;
|
|
|
|
}
|
|
|
|
|
|
|
|
void laikaS_freePeer(struct sLaika_peer *peer) {
|
|
|
|
laikaS_cleanSocket(&peer->sock);
|
|
|
|
laikaM_free(peer);
|
|
|
|
}
|
|
|
|
|
2022-02-04 02:51:32 +00:00
|
|
|
void laikaS_startOutPacket(struct sLaika_peer *peer, uint8_t id) {
|
|
|
|
struct sLaika_socket *sock = &peer->sock;
|
|
|
|
|
|
|
|
if (peer->outStart != -1) { /* sanity check */
|
|
|
|
LAIKA_ERROR("unended OUT packet!\n")
|
|
|
|
}
|
|
|
|
laikaS_writeByte(sock, id);
|
|
|
|
|
|
|
|
peer->outStart = sock->outCount;
|
|
|
|
if (peer->useSecure) { /* if we're encrypting this packet, append the nonce right after the packet ID */
|
|
|
|
uint8_t nonce[crypto_secretbox_NONCEBYTES];
|
|
|
|
randombytes_buf(nonce, crypto_secretbox_NONCEBYTES);
|
|
|
|
laikaS_write(sock, nonce, crypto_secretbox_NONCEBYTES);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int laikaS_endOutPacket(struct sLaika_peer *peer) {
|
|
|
|
struct sLaika_socket *sock = &peer->sock;
|
|
|
|
uint8_t *body;
|
|
|
|
size_t sz;
|
|
|
|
|
|
|
|
if (peer->useSecure) {
|
|
|
|
/* make sure we have enough space */
|
|
|
|
laikaM_growarray(uint8_t, sock->outBuf, crypto_secretbox_MACBYTES, sock->outCount, sock->outCap);
|
|
|
|
|
|
|
|
/* packet body starts after the id & nonce */
|
|
|
|
body = &sock->outBuf[peer->outStart + crypto_secretbox_NONCEBYTES];
|
|
|
|
/* encrypt packet body in-place */
|
|
|
|
if (crypto_secretbox_easy(body, body, (sock->outCount - peer->outStart) - crypto_secretbox_NONCEBYTES,
|
|
|
|
&sock->outBuf[peer->outStart], peer->outKey) != 0) {
|
|
|
|
LAIKA_ERROR("Failed to encrypt packet!\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
sock->outCount += crypto_secretbox_MACBYTES;
|
|
|
|
}
|
|
|
|
|
|
|
|
sz = sock->outCount - peer->outStart;
|
|
|
|
peer->outStart = -1;
|
|
|
|
return sz;
|
|
|
|
}
|
|
|
|
|
|
|
|
void laikaS_startInPacket(struct sLaika_peer *peer) {
|
|
|
|
struct sLaika_socket *sock = &peer->sock;
|
|
|
|
|
|
|
|
if (peer->inStart != -1) { /* sanity check */
|
|
|
|
LAIKA_ERROR("unended IN packet!\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
peer->inStart = sock->inCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
int laikaS_endInPacket(struct sLaika_peer *peer) {
|
|
|
|
struct sLaika_socket *sock = &peer->sock;
|
|
|
|
uint8_t *body;
|
|
|
|
size_t sz = sock->inCount - peer->inStart;
|
|
|
|
|
|
|
|
if (peer->useSecure) {
|
|
|
|
body = &sock->inBuf[peer->inStart + crypto_secretbox_NONCEBYTES];
|
|
|
|
|
|
|
|
/* decrypt packet body in-place */
|
|
|
|
if (crypto_secretbox_open_easy(body, body, (sock->inCount - peer->inStart) - crypto_secretbox_NONCEBYTES,
|
|
|
|
&sock->inBuf[peer->inStart], peer->inKey) != 0) {
|
|
|
|
LAIKA_ERROR("Failed to decrypt packet!\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
/* decrypted message is smaller now */
|
|
|
|
sock->inCount -= crypto_secretbox_MACBYTES;
|
|
|
|
|
|
|
|
/* remove nonce */
|
|
|
|
laikaM_rmvarray(sock->inBuf, sock->inCount, peer->inStart, crypto_secretbox_NONCEBYTES);
|
|
|
|
|
|
|
|
sz -= crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES;
|
|
|
|
}
|
|
|
|
|
|
|
|
peer->inStart = -1;
|
|
|
|
return sz;
|
|
|
|
}
|
|
|
|
|
|
|
|
void laikaS_setSecure(struct sLaika_peer *peer, bool flag) {
|
|
|
|
peer->useSecure = flag;
|
|
|
|
}
|
|
|
|
|
2022-01-24 03:28:16 +00:00
|
|
|
bool laikaS_handlePeerIn(struct sLaika_peer *peer) {
|
|
|
|
RAWSOCKCODE err;
|
|
|
|
int recvd;
|
|
|
|
|
|
|
|
switch (peer->pktID) {
|
|
|
|
case LAIKAPKT_MAXNONE:
|
|
|
|
/* try grabbing pktID */
|
|
|
|
if (laikaS_rawRecv(&peer->sock, sizeof(uint8_t), &recvd) != RAWSOCK_OK)
|
|
|
|
return false;
|
|
|
|
|
2022-02-04 02:51:32 +00:00
|
|
|
/* read packet ID & mark start of packet */
|
2022-01-24 03:28:16 +00:00
|
|
|
peer->pktID = laikaS_readByte(&peer->sock);
|
2022-02-04 02:51:32 +00:00
|
|
|
laikaS_startInPacket(peer);
|
2022-01-24 03:28:16 +00:00
|
|
|
|
|
|
|
/* sanity check packet ID */
|
|
|
|
if (peer->pktID >= LAIKAPKT_MAXNONE)
|
2022-01-25 03:46:29 +00:00
|
|
|
LAIKA_ERROR("received evil pktID!\n")
|
2022-01-24 03:28:16 +00:00
|
|
|
|
|
|
|
peer->pktSize = peer->pktSizeTable[peer->pktID];
|
2022-01-28 02:10:41 +00:00
|
|
|
|
|
|
|
if (peer->pktSize == 0)
|
|
|
|
LAIKA_ERROR("unsupported packet!\n")
|
|
|
|
|
2022-02-03 22:25:49 +00:00
|
|
|
/* if we're encrypting/decrypting all packets, make sure to make the packetsize reflect this */
|
2022-02-04 02:51:32 +00:00
|
|
|
if (peer->useSecure)
|
2022-02-03 22:25:49 +00:00
|
|
|
peer->pktSize += crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES;
|
|
|
|
|
2022-01-24 03:28:16 +00:00
|
|
|
break;
|
2022-02-03 22:25:49 +00:00
|
|
|
//case LAIKAPKT_VARPKT_REQ:
|
2022-01-25 19:53:17 +00:00
|
|
|
/* try grabbing pktID & size */
|
2022-02-03 22:25:49 +00:00
|
|
|
// if (laikaS_rawRecv(&peer->sock, sizeof(uint8_t) + sizeof(LAIKAPKT_SIZE), &recvd) != RAWSOCK_OK)
|
|
|
|
// return false;
|
2022-01-25 19:53:17 +00:00
|
|
|
|
2022-02-03 22:25:49 +00:00
|
|
|
// if (recvd != sizeof(uint8_t) + sizeof(LAIKAPKT_SIZE))
|
|
|
|
// LAIKA_ERROR("couldn't read whole LAIKAPKT_VARPKT_REQ")
|
2022-01-25 19:53:17 +00:00
|
|
|
|
2022-01-29 06:26:15 +00:00
|
|
|
/* read pktID */
|
2022-02-03 22:25:49 +00:00
|
|
|
// peer->pktID = laikaS_readByte(&peer->sock);
|
2022-01-25 19:53:17 +00:00
|
|
|
|
2022-01-29 06:26:15 +00:00
|
|
|
/* sanity check pktID, (check valid range, check it's variadic) */
|
2022-02-03 22:25:49 +00:00
|
|
|
// if (peer->pktID >= LAIKAPKT_MAXNONE || peer->pktSizeTable[peer->pktID])
|
|
|
|
// LAIKA_ERROR("received evil pktID!\n")
|
2022-01-25 19:53:17 +00:00
|
|
|
|
|
|
|
/* try reading new packet size */
|
2022-02-03 22:25:49 +00:00
|
|
|
// laikaS_readInt(&peer->sock, (void*)&peer->pktSize, sizeof(LAIKAPKT_SIZE));
|
2022-01-25 19:53:17 +00:00
|
|
|
|
2022-02-03 22:25:49 +00:00
|
|
|
// if (peer->pktSize > LAIKA_MAX_PKTSIZE)
|
|
|
|
// LAIKA_ERROR("variable packet too large!")
|
|
|
|
// break;
|
2022-01-24 03:28:16 +00:00
|
|
|
default:
|
|
|
|
/* try grabbing the rest of the packet */
|
|
|
|
if (laikaS_rawRecv(&peer->sock, peer->pktSize - peer->sock.inCount, &recvd) != RAWSOCK_OK)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/* have we received the full packet? */
|
|
|
|
if (peer->pktSize == peer->sock.inCount) {
|
2022-01-31 01:10:10 +00:00
|
|
|
PeerPktHandler hndlr = peer->handlers[peer->pktID];
|
2022-02-04 02:51:32 +00:00
|
|
|
peer->pktSize = laikaS_endInPacket(peer);
|
2022-01-31 01:10:10 +00:00
|
|
|
|
|
|
|
if (hndlr != NULL) {
|
2022-02-03 22:25:49 +00:00
|
|
|
hndlr(peer, peer->pktSize, peer->uData); /* dispatch to packet handler */
|
2022-01-31 01:10:10 +00:00
|
|
|
} else
|
|
|
|
LAIKA_ERROR("peer %x doesn't support packet id [%d]!\n", peer, peer->pktID);
|
2022-01-24 16:34:30 +00:00
|
|
|
|
|
|
|
/* reset */
|
|
|
|
peer->sock.inCount = 0;
|
|
|
|
peer->pktID = LAIKAPKT_MAXNONE;
|
2022-01-24 03:28:16 +00:00
|
|
|
}
|
2022-01-24 16:34:30 +00:00
|
|
|
|
|
|
|
break;
|
2022-01-24 03:28:16 +00:00
|
|
|
}
|
2022-01-24 16:34:30 +00:00
|
|
|
|
|
|
|
if (peer->sock.outCount > 0 && !laikaS_handlePeerOut(peer))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return laikaS_isAlive((&peer->sock));
|
2022-01-24 03:28:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool laikaS_handlePeerOut(struct sLaika_peer *peer) {
|
|
|
|
RAWSOCKCODE err;
|
|
|
|
int sent;
|
|
|
|
|
|
|
|
if (peer->sock.outCount == 0) /* sanity check */
|
2022-01-25 03:46:29 +00:00
|
|
|
return true;
|
2022-01-24 03:28:16 +00:00
|
|
|
|
|
|
|
switch (laikaS_rawSend(&peer->sock, peer->sock.outCount, &sent)) {
|
|
|
|
case RAWSOCK_OK: /* we're ok! */
|
|
|
|
if (peer->setPollOut) { /* if POLLOUT was set, unset it */
|
|
|
|
laikaP_rmvPollOut(peer->pList, &peer->sock);
|
|
|
|
peer->setPollOut = false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
case RAWSOCK_POLL: /* we've been asked to set the POLLOUT flag */
|
|
|
|
if (!peer->setPollOut) { /* if POLLOUT wasn't set, set it so we'll be notified whenever the kernel has room :) */
|
|
|
|
laikaP_addPollOut(peer->pList, &peer->sock);
|
|
|
|
peer->setPollOut = true;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
default: /* panic! */
|
|
|
|
case RAWSOCK_CLOSED:
|
|
|
|
case RAWSOCK_ERROR:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|