2022-06-27 23:57:00 +00:00
|
|
|
#include "lsocket.h"
|
|
|
|
|
2022-01-24 03:28:16 +00:00
|
|
|
#include "lerror.h"
|
|
|
|
#include "lmem.h"
|
2022-06-27 23:57:00 +00:00
|
|
|
#include "lpacket.h"
|
2022-01-24 03:28:16 +00:00
|
|
|
#include "lpolllist.h"
|
2022-02-25 04:13:05 +00:00
|
|
|
#include "lsodium.h"
|
2022-01-24 03:28:16 +00:00
|
|
|
|
|
|
|
static int _LNSetup = 0;
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
bool laikaS_isBigEndian(void)
|
|
|
|
{
|
|
|
|
union
|
|
|
|
{
|
2022-01-25 18:13:04 +00:00
|
|
|
uint32_t i;
|
|
|
|
uint8_t c[4];
|
|
|
|
} _indxint = {0xDEADB33F};
|
|
|
|
|
|
|
|
return _indxint.c[0] == 0xDE;
|
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_init(void)
|
|
|
|
{
|
2022-01-24 03:28:16 +00:00
|
|
|
if (_LNSetup++ > 0)
|
|
|
|
return; /* WSA is already setup! */
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
WSADATA wsaData;
|
|
|
|
|
|
|
|
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
|
2022-02-28 22:27:55 +00:00
|
|
|
LAIKA_ERROR("WSAStartup failed!\n");
|
2022-01-24 03:28:16 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_cleanUp(void)
|
|
|
|
{
|
2022-01-24 03:28:16 +00:00
|
|
|
if (--_LNSetup > 0)
|
2022-03-28 20:49:50 +00:00
|
|
|
return; /* WSA still needs to be up, a socket is still running */
|
2022-01-24 03:28:16 +00:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
WSACleanup();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_initSocket(struct sLaika_socket *sock, pollEvent onPollIn, pollEvent onPollOut,
|
|
|
|
pollFailEvent onPollFail, void *uData)
|
|
|
|
{
|
2022-01-24 03:28:16 +00:00
|
|
|
sock->sock = INVALID_SOCKET;
|
2022-03-24 15:26:06 +00:00
|
|
|
sock->onPollFail = onPollFail;
|
|
|
|
sock->onPollIn = onPollIn;
|
|
|
|
sock->onPollOut = onPollOut;
|
|
|
|
sock->uData = uData;
|
2022-01-24 03:28:16 +00:00
|
|
|
sock->inBuf = NULL;
|
2022-05-03 20:54:42 +00:00
|
|
|
sock->inCap = 8;
|
2022-01-24 03:28:16 +00:00
|
|
|
sock->inCount = 0;
|
|
|
|
sock->outBuf = NULL;
|
2022-05-03 20:54:42 +00:00
|
|
|
sock->outCap = 8;
|
2022-01-24 03:28:16 +00:00
|
|
|
sock->outCount = 0;
|
2022-01-25 02:50:14 +00:00
|
|
|
sock->flipEndian = false;
|
2022-03-27 22:32:32 +00:00
|
|
|
sock->setPollOut = false;
|
2022-01-24 03:28:16 +00:00
|
|
|
|
|
|
|
laikaS_init();
|
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_cleanSocket(struct sLaika_socket *sock)
|
|
|
|
{
|
2022-01-24 03:28:16 +00:00
|
|
|
/* free in & out arrays */
|
|
|
|
laikaM_free(sock->inBuf);
|
|
|
|
laikaM_free(sock->outBuf);
|
|
|
|
|
|
|
|
/* kill socket & cleanup WSA */
|
|
|
|
laikaS_kill(sock);
|
|
|
|
laikaS_cleanUp();
|
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_kill(struct sLaika_socket *sock)
|
|
|
|
{
|
2022-01-24 03:28:16 +00:00
|
|
|
if (!laikaS_isAlive(sock)) /* sanity check */
|
|
|
|
return;
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
shutdown(sock->sock, SD_BOTH);
|
|
|
|
closesocket(sock->sock);
|
|
|
|
#else
|
|
|
|
shutdown(sock->sock, SHUT_RDWR);
|
|
|
|
close(sock->sock);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
sock->sock = INVALID_SOCKET;
|
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_connect(struct sLaika_socket *sock, char *ip, char *port)
|
|
|
|
{
|
2022-01-24 03:28:16 +00:00
|
|
|
struct addrinfo res, *result, *curr;
|
|
|
|
|
|
|
|
if (!SOCKETINVALID(sock->sock))
|
2022-01-25 03:46:29 +00:00
|
|
|
LAIKA_ERROR("socket already setup!\n");
|
2022-01-24 03:28:16 +00:00
|
|
|
|
|
|
|
/* zero out our address info and setup the type */
|
|
|
|
memset(&res, 0, sizeof(struct addrinfo));
|
|
|
|
res.ai_family = AF_UNSPEC;
|
|
|
|
res.ai_socktype = SOCK_STREAM;
|
|
|
|
|
|
|
|
/* grab the address info */
|
|
|
|
if (getaddrinfo(ip, port, &res, &result) != 0)
|
2022-01-25 03:46:29 +00:00
|
|
|
LAIKA_ERROR("getaddrinfo() failed!\n");
|
2022-01-24 03:28:16 +00:00
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
/* getaddrinfo returns a list of possible addresses, step through them and try them until we
|
|
|
|
* find a valid address */
|
2022-01-24 03:28:16 +00:00
|
|
|
for (curr = result; curr != NULL; curr = curr->ai_next) {
|
|
|
|
sock->sock = socket(curr->ai_family, curr->ai_socktype, curr->ai_protocol);
|
|
|
|
|
|
|
|
/* if it failed, try the next sock */
|
|
|
|
if (SOCKETINVALID(sock->sock))
|
|
|
|
continue;
|
2022-06-27 23:57:00 +00:00
|
|
|
|
2022-01-24 03:28:16 +00:00
|
|
|
/* if it's not an invalid socket, break and exit the loop, we found a working addr! */
|
|
|
|
if (!SOCKETINVALID(connect(sock->sock, curr->ai_addr, curr->ai_addrlen)))
|
|
|
|
break;
|
|
|
|
|
|
|
|
laikaS_kill(sock);
|
|
|
|
}
|
|
|
|
freeaddrinfo(result);
|
|
|
|
|
|
|
|
/* if we reached the end of the linked list, we failed looking up the addr */
|
|
|
|
if (curr == NULL)
|
2022-01-25 03:46:29 +00:00
|
|
|
LAIKA_ERROR("couldn't connect a valid address handle to socket!\n");
|
2022-01-24 03:28:16 +00:00
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_bind(struct sLaika_socket *sock, uint16_t port)
|
|
|
|
{
|
2022-01-24 03:28:16 +00:00
|
|
|
socklen_t addressSize;
|
2022-06-04 15:11:28 +00:00
|
|
|
struct sockaddr_in6 address;
|
2022-03-28 20:49:50 +00:00
|
|
|
int opt = 1;
|
2022-01-24 03:28:16 +00:00
|
|
|
|
2022-01-25 03:46:29 +00:00
|
|
|
if (!SOCKETINVALID(sock->sock))
|
2022-02-28 22:27:55 +00:00
|
|
|
LAIKA_ERROR("socket already setup!\n");
|
2022-01-24 03:28:16 +00:00
|
|
|
|
|
|
|
/* open our socket */
|
2022-06-04 15:11:28 +00:00
|
|
|
sock->sock = socket(AF_INET6, SOCK_STREAM, 0);
|
2022-01-25 03:46:29 +00:00
|
|
|
if (SOCKETINVALID(sock->sock))
|
|
|
|
LAIKA_ERROR("socket() failed!\n");
|
2022-01-24 03:28:16 +00:00
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
/* allow reuse of local address */
|
2022-01-24 03:28:16 +00:00
|
|
|
#ifdef _WIN32
|
2022-06-27 23:57:00 +00:00
|
|
|
if (setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(int)) != 0)
|
2022-01-24 03:28:16 +00:00
|
|
|
#else
|
|
|
|
if (setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)) != 0)
|
|
|
|
#endif
|
2022-01-25 03:46:29 +00:00
|
|
|
LAIKA_ERROR("setsockopt() failed!\n");
|
2022-01-24 03:28:16 +00:00
|
|
|
|
2022-06-04 15:11:28 +00:00
|
|
|
address.sin6_family = AF_INET6;
|
|
|
|
address.sin6_addr = in6addr_any;
|
|
|
|
address.sin6_port = htons(port);
|
2022-01-24 03:28:16 +00:00
|
|
|
|
2022-06-04 15:11:28 +00:00
|
|
|
addressSize = sizeof(address);
|
2022-01-24 03:28:16 +00:00
|
|
|
|
|
|
|
/* bind to the port */
|
2022-06-27 23:57:00 +00:00
|
|
|
if (SOCKETERROR(bind(sock->sock, (struct sockaddr *)&address, addressSize)))
|
2022-01-25 03:46:29 +00:00
|
|
|
LAIKA_ERROR("bind() failed!\n");
|
2022-01-24 03:28:16 +00:00
|
|
|
|
|
|
|
if (SOCKETERROR(listen(sock->sock, SOMAXCONN)))
|
2022-01-25 03:46:29 +00:00
|
|
|
LAIKA_ERROR("listen() failed!\n");
|
2022-01-24 03:28:16 +00:00
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_acceptFrom(struct sLaika_socket *sock, struct sLaika_socket *from, char *ip)
|
|
|
|
{
|
2022-06-04 15:11:28 +00:00
|
|
|
struct sockaddr_in6 address;
|
|
|
|
socklen_t addressSize = sizeof(address);
|
2022-01-24 03:28:16 +00:00
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
sock->sock = accept(from->sock, (struct sockaddr *)&address, &addressSize);
|
2022-01-25 03:46:29 +00:00
|
|
|
if (SOCKETINVALID(sock->sock))
|
2022-02-28 22:27:55 +00:00
|
|
|
LAIKA_ERROR("accept() failed!\n");
|
2022-03-05 02:17:03 +00:00
|
|
|
|
2022-06-04 15:11:28 +00:00
|
|
|
/* read ip */
|
|
|
|
if (ip) {
|
|
|
|
if (inet_ntop(AF_INET6, &address.sin6_addr, ip, LAIKA_IPSTR_LEN) == NULL)
|
2022-03-05 02:17:03 +00:00
|
|
|
LAIKA_ERROR("inet_ntop() failed!\n");
|
|
|
|
}
|
2022-01-24 03:28:16 +00:00
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
bool laikaS_setNonBlock(struct sLaika_socket *sock)
|
|
|
|
{
|
2022-01-24 03:28:16 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
unsigned long mode = 1;
|
|
|
|
if (ioctlsocket(sock->sock, FIONBIO, &mode) != 0) {
|
|
|
|
#else
|
|
|
|
if (fcntl(sock->sock, F_SETFL, (fcntl(sock->sock, F_GETFL, 0) | O_NONBLOCK)) != 0) {
|
|
|
|
#endif
|
2022-01-25 03:46:29 +00:00
|
|
|
LAIKA_WARN("fcntl failed on new connection\n");
|
2022-01-24 03:28:16 +00:00
|
|
|
laikaS_kill(sock);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_consumeRead(struct sLaika_socket *sock, size_t sz)
|
|
|
|
{
|
2022-02-10 22:56:40 +00:00
|
|
|
laikaM_rmvarray(sock->inBuf, sock->inCount, 0, sz);
|
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_zeroWrite(struct sLaika_socket *sock, size_t sz)
|
|
|
|
{
|
2022-02-15 22:57:21 +00:00
|
|
|
laikaM_growarray(uint8_t, sock->outBuf, sz, sock->outCount, sock->outCap);
|
|
|
|
|
|
|
|
/* set NULL bytes */
|
|
|
|
memset(&sock->outBuf[sock->outCount], 0, sz);
|
|
|
|
sock->outCount += sz;
|
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_read(struct sLaika_socket *sock, void *buf, size_t sz)
|
|
|
|
{
|
2022-01-24 03:28:16 +00:00
|
|
|
memcpy(buf, sock->inBuf, sz);
|
2022-01-31 21:54:39 +00:00
|
|
|
laikaM_rmvarray(sock->inBuf, sock->inCount, 0, sz);
|
2022-01-24 03:28:16 +00:00
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_write(struct sLaika_socket *sock, void *buf, size_t sz)
|
|
|
|
{
|
2022-01-24 03:28:16 +00:00
|
|
|
/* make sure we have enough space to copy the buffer */
|
2022-02-03 22:25:49 +00:00
|
|
|
laikaM_growarray(uint8_t, sock->outBuf, sz, sock->outCount, sock->outCap);
|
2022-01-24 03:28:16 +00:00
|
|
|
|
|
|
|
/* copy the buffer, then increment outCount */
|
|
|
|
memcpy(&sock->outBuf[sock->outCount], buf, sz);
|
|
|
|
sock->outCount += sz;
|
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_writeKeyEncrypt(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub)
|
|
|
|
{
|
2022-01-29 06:26:15 +00:00
|
|
|
/* make sure we have enough space to encrypt the buffer */
|
|
|
|
laikaM_growarray(uint8_t, sock->outBuf, LAIKAENC_SIZE(sz), sock->outCount, sock->outCap);
|
|
|
|
|
|
|
|
/* encrypt the buffer into outBuf */
|
|
|
|
if (crypto_box_seal(&sock->outBuf[sock->outCount], buf, sz, pub) != 0)
|
2022-01-31 01:10:10 +00:00
|
|
|
LAIKA_ERROR("Failed to encrypt!\n");
|
2022-01-29 06:26:15 +00:00
|
|
|
|
|
|
|
sock->outCount += LAIKAENC_SIZE(sz);
|
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_readKeyDecrypt(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub,
|
|
|
|
uint8_t *priv)
|
|
|
|
{
|
2022-01-29 06:26:15 +00:00
|
|
|
/* decrypt into buf */
|
|
|
|
if (crypto_box_seal_open(buf, sock->inBuf, LAIKAENC_SIZE(sz), pub, priv) != 0)
|
2022-01-31 01:10:10 +00:00
|
|
|
LAIKA_ERROR("Failed to decrypt!\n");
|
2022-01-29 06:26:15 +00:00
|
|
|
|
2022-01-31 21:54:39 +00:00
|
|
|
laikaM_rmvarray(sock->inBuf, sock->inCount, 0, LAIKAENC_SIZE(sz));
|
2022-01-29 06:26:15 +00:00
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_writeByte(struct sLaika_socket *sock, uint8_t data)
|
|
|
|
{
|
2022-01-28 01:55:28 +00:00
|
|
|
laikaM_growarray(uint8_t, sock->outBuf, 1, sock->outCount, sock->outCap);
|
2022-01-24 03:28:16 +00:00
|
|
|
sock->outBuf[sock->outCount++] = data;
|
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
uint8_t laikaS_readByte(struct sLaika_socket *sock)
|
|
|
|
{
|
2022-01-24 03:28:16 +00:00
|
|
|
uint8_t tmp = *sock->inBuf;
|
|
|
|
|
|
|
|
/* pop 1 byte */
|
2022-01-31 21:54:39 +00:00
|
|
|
laikaM_rmvarray(sock->inBuf, sock->inCount, 0, 1);
|
2022-01-24 03:28:16 +00:00
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_readInt(struct sLaika_socket *sock, void *buf, size_t sz)
|
|
|
|
{
|
2022-01-25 02:50:14 +00:00
|
|
|
if (sock->flipEndian) {
|
2022-03-14 17:06:32 +00:00
|
|
|
VLA(uint8_t, tmp, sz); /* allocate tmp buffer to hold data while we switch endianness */
|
2022-01-25 02:50:14 +00:00
|
|
|
int k;
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
laikaS_read(sock, (void *)tmp, sz);
|
2022-01-25 02:50:14 +00:00
|
|
|
|
|
|
|
/* copy tmp buffer to user buffer, flipping endianness */
|
|
|
|
for (k = 0; k < sz; k++)
|
2022-06-27 23:57:00 +00:00
|
|
|
*((uint8_t *)buf + k) = tmp[sz - k - 1];
|
|
|
|
|
2022-03-14 17:06:32 +00:00
|
|
|
ENDVLA(tmp);
|
2022-01-25 02:50:14 +00:00
|
|
|
} else {
|
|
|
|
/* just a wrapper for laikaS_read */
|
|
|
|
laikaS_read(sock, buf, sz);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
void laikaS_writeInt(struct sLaika_socket *sock, void *buf, size_t sz)
|
|
|
|
{
|
2022-01-25 02:50:14 +00:00
|
|
|
if (sock->flipEndian) {
|
2022-03-14 17:06:32 +00:00
|
|
|
VLA(uint8_t, tmp, sz); /* allocate tmp buffer to hold data while we switch endianness */
|
2022-01-25 02:50:14 +00:00
|
|
|
int k;
|
|
|
|
|
|
|
|
/* copy user buffer to tmp buffer, flipping endianness */
|
|
|
|
for (k = 0; k < sz; k++)
|
2022-06-27 23:57:00 +00:00
|
|
|
tmp[k] = *((uint8_t *)buf + (sz - k - 1));
|
2022-01-25 02:50:14 +00:00
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
laikaS_write(sock, (void *)tmp, sz);
|
2022-03-14 17:06:32 +00:00
|
|
|
ENDVLA(tmp);
|
2022-01-25 02:50:14 +00:00
|
|
|
} else {
|
|
|
|
/* just a wrapper for laikaS_write */
|
|
|
|
laikaS_write(sock, buf, sz);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
RAWSOCKCODE laikaS_rawRecv(struct sLaika_socket *sock, size_t sz, int *processed)
|
|
|
|
{
|
2022-01-24 03:28:16 +00:00
|
|
|
RAWSOCKCODE errCode = RAWSOCK_OK;
|
2022-03-28 20:49:50 +00:00
|
|
|
int i, rcvd, start = sock->inCount;
|
2022-01-24 03:28:16 +00:00
|
|
|
|
2022-02-28 22:27:55 +00:00
|
|
|
/* sanity check */
|
|
|
|
if (sz == 0)
|
|
|
|
return RAWSOCK_OK;
|
|
|
|
|
2022-01-24 03:28:16 +00:00
|
|
|
/* make sure we have enough space to recv */
|
2022-01-28 01:55:28 +00:00
|
|
|
laikaM_growarray(uint8_t, sock->inBuf, sz, sock->inCount, sock->inCap);
|
2022-06-27 23:57:00 +00:00
|
|
|
rcvd = recv(sock->sock, (buffer_t *)&sock->inBuf[sock->inCount], sz, LN_MSG_NOSIGNAL);
|
2022-01-24 03:28:16 +00:00
|
|
|
|
|
|
|
if (rcvd == 0) {
|
|
|
|
errCode = RAWSOCK_CLOSED;
|
2022-06-27 23:57:00 +00:00
|
|
|
} else if (SOCKETERROR(rcvd) &&
|
|
|
|
LN_ERRNO != LN_EWOULD
|
2022-01-24 03:28:16 +00:00
|
|
|
#ifndef _WIN32
|
2022-06-27 23:57:00 +00:00
|
|
|
/* if it's a posix system, also make sure its not a EAGAIN result (which is a
|
|
|
|
recoverable error, there's just nothing to read lol) */
|
|
|
|
&& LN_ERRNO != EAGAIN
|
2022-01-24 03:28:16 +00:00
|
|
|
#endif
|
|
|
|
) {
|
|
|
|
/* if the socket closed or an error occurred, return the error result */
|
|
|
|
errCode = RAWSOCK_ERROR;
|
|
|
|
} else if (rcvd > 0) {
|
2022-04-13 17:19:06 +00:00
|
|
|
#if 0
|
2022-02-04 02:51:32 +00:00
|
|
|
/* for debugging */
|
|
|
|
printf("---recv'd %d bytes---\n", rcvd);
|
|
|
|
for (i = 1; i <= rcvd; i++) {
|
|
|
|
printf("%.2x ", sock->inBuf[sock->inCount + (i-1)]);
|
|
|
|
if (i % 16 == 0) {
|
|
|
|
printf("\n");
|
|
|
|
} else if (i % 8 == 0) {
|
|
|
|
printf("\t");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
#endif
|
|
|
|
|
2022-01-24 03:28:16 +00:00
|
|
|
/* recv() worked, add rcvd to inCount */
|
|
|
|
sock->inCount += rcvd;
|
|
|
|
}
|
|
|
|
*processed = rcvd;
|
|
|
|
return errCode;
|
|
|
|
}
|
|
|
|
|
2022-06-27 23:57:00 +00:00
|
|
|
RAWSOCKCODE laikaS_rawSend(struct sLaika_socket *sock, size_t sz, int *processed)
|
|
|
|
{
|
2022-01-24 03:28:16 +00:00
|
|
|
RAWSOCKCODE errCode = RAWSOCK_OK;
|
2022-02-17 22:55:42 +00:00
|
|
|
int sent, i, sentBytes = 0;
|
2022-01-24 03:28:16 +00:00
|
|
|
|
|
|
|
/* write bytes to the socket until an error occurs or we finish sending */
|
|
|
|
do {
|
2022-06-27 23:57:00 +00:00
|
|
|
sent = send(sock->sock, (buffer_t *)(&sock->outBuf[sentBytes]), sz - sentBytes,
|
|
|
|
LN_MSG_NOSIGNAL);
|
2022-01-24 03:28:16 +00:00
|
|
|
|
|
|
|
/* check for error result */
|
|
|
|
if (sent == 0) { /* connection closed gracefully */
|
|
|
|
errCode = RAWSOCK_CLOSED;
|
|
|
|
goto _rawWriteExit;
|
|
|
|
} else if (SOCKETERROR(sent)) { /* socket error? */
|
|
|
|
if (LN_ERRNO != LN_EWOULD
|
|
|
|
#ifndef _WIN32
|
2022-06-27 23:57:00 +00:00
|
|
|
/* posix also has some platforms which define EAGAIN as a different value than
|
|
|
|
EWOULD, might as well support it. */
|
2022-01-24 03:28:16 +00:00
|
|
|
&& LN_ERRNO != EAGAIN
|
|
|
|
#endif
|
|
|
|
) { /* socket error! */
|
|
|
|
errCode = RAWSOCK_ERROR;
|
|
|
|
goto _rawWriteExit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
it was a result of EWOULD or EAGAIN, kernel socket send buffer is full,
|
|
|
|
tell the caller we need to set our poll event POLLOUT
|
|
|
|
*/
|
|
|
|
errCode = RAWSOCK_POLL;
|
|
|
|
goto _rawWriteExit;
|
|
|
|
}
|
2022-06-27 23:57:00 +00:00
|
|
|
} while ((sentBytes += sent) < sz);
|
2022-01-24 03:28:16 +00:00
|
|
|
|
|
|
|
_rawWriteExit:
|
2022-04-13 17:19:06 +00:00
|
|
|
#if 0
|
2022-02-04 02:51:32 +00:00
|
|
|
/* for debugging */
|
|
|
|
printf("---sent %d bytes---\n", sent);
|
|
|
|
for (i = 1; i <= sentBytes; i++) {
|
|
|
|
printf("%.2x ", sock->outBuf[i-1]);
|
|
|
|
if (i % 16 == 0) {
|
|
|
|
printf("\n");
|
|
|
|
} else if (i % 8 == 0) {
|
|
|
|
printf("\t");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
#endif
|
|
|
|
|
2022-01-24 03:28:16 +00:00
|
|
|
/* trim sent data from outBuf */
|
2022-01-31 21:54:39 +00:00
|
|
|
laikaM_rmvarray(sock->outBuf, sock->outCount, 0, sentBytes);
|
2022-01-24 03:28:16 +00:00
|
|
|
|
|
|
|
*processed = sentBytes;
|
|
|
|
return errCode;
|
|
|
|
}
|