Laika/lib/src/lpeer.c

128 lines
4.4 KiB
C
Raw Normal View History

#include "lerror.h"
#include "lmem.h"
#include "lpeer.h"
struct sLaika_peer *laikaS_newPeer(PeerPktHandler *handlers, LAIKAPKT_SIZE *pktSizeTable, struct sLaika_pollList *pList, void *uData) {
struct sLaika_peer *peer = laikaM_malloc(sizeof(struct sLaika_peer));
laikaS_initSocket(&peer->sock);
peer->handlers = handlers;
peer->pktSizeTable = pktSizeTable;
peer->pList = pList;
peer->uData = uData;
peer->pktSize = 0;
peer->type = PEER_UNVERIFIED;
peer->pktID = LAIKAPKT_MAXNONE;
peer->setPollOut = false;
return peer;
}
void laikaS_freePeer(struct sLaika_peer *peer) {
laikaS_cleanSocket(&peer->sock);
laikaM_free(peer);
}
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;
peer->pktID = laikaS_readByte(&peer->sock);
laikaS_startInPacket(&peer->sock);
/* sanity check packet ID */
if (peer->pktID >= LAIKAPKT_MAXNONE)
LAIKA_ERROR("received evil pktID!\n")
peer->pktSize = peer->pktSizeTable[peer->pktID];
2022-01-28 02:10:41 +00:00
if (peer->pktSize == 0)
LAIKA_ERROR("unsupported packet!\n")
/* if we're encrypting/decrypting all packets, make sure to make the packetsize reflect this */
if (peer->sock.useSecure)
peer->pktSize += crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES;
break;
//case LAIKAPKT_VARPKT_REQ:
/* try grabbing pktID & size */
// if (laikaS_rawRecv(&peer->sock, sizeof(uint8_t) + sizeof(LAIKAPKT_SIZE), &recvd) != RAWSOCK_OK)
// return false;
// if (recvd != sizeof(uint8_t) + sizeof(LAIKAPKT_SIZE))
// LAIKA_ERROR("couldn't read whole LAIKAPKT_VARPKT_REQ")
/* read pktID */
// peer->pktID = laikaS_readByte(&peer->sock);
/* sanity check pktID, (check valid range, check it's variadic) */
// if (peer->pktID >= LAIKAPKT_MAXNONE || peer->pktSizeTable[peer->pktID])
// LAIKA_ERROR("received evil pktID!\n")
/* try reading new packet size */
// laikaS_readInt(&peer->sock, (void*)&peer->pktSize, sizeof(LAIKAPKT_SIZE));
// if (peer->pktSize > LAIKA_MAX_PKTSIZE)
// LAIKA_ERROR("variable packet too large!")
// break;
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) {
PeerPktHandler hndlr = peer->handlers[peer->pktID];
peer->pktSize = laikaS_endInPacket(&peer->sock);
if (hndlr != NULL) {
hndlr(peer, peer->pktSize, peer->uData); /* dispatch to packet handler */
} else
LAIKA_ERROR("peer %x doesn't support packet id [%d]!\n", peer, peer->pktID);
/* reset */
peer->sock.inCount = 0;
peer->pktID = LAIKAPKT_MAXNONE;
}
break;
}
if (peer->sock.outCount > 0 && !laikaS_handlePeerOut(peer))
return false;
return laikaS_isAlive((&peer->sock));
}
bool laikaS_handlePeerOut(struct sLaika_peer *peer) {
RAWSOCKCODE err;
int sent;
if (peer->sock.outCount == 0) /* sanity check */
return true;
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;
}
}