cake
/
libp7
Archived
1
0
Fork 1
This repository has been archived on 2024-03-16. You can view files and clone it, but cannot push or open issues or pull requests.
libp7/src/protocol/seven/send.c

217 lines
6.0 KiB
C

/* *****************************************************************************
* protocol/seven/send.c -- prepare and send a packet.
* Copyright (C) 2016-2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libp7.
* libp7 is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libp7 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libp7; if not, see <http://www.gnu.org/licenses/>.
*
* These functions are the one used behind the others to send a packet.
* ************************************************************************** */
#include <libp7/internals.h>
#include <stdio.h>
#include <string.h>
#define buffer \
handle->_send_buffers[handle->_flags & p7_intflag_sendalt]
#define buffer_size \
handle->_send_buffers_size[handle->_flags & p7_intflag_sendalt]
#define switch_buffer() \
if (handle->_flags & p7_intflag_shifted) \
handle->_flags = (handle->_flags & ~p7_intflag_sendalt) | \
(~handle->_flags & p7_intflag_sendalt);
/* ************************************************************************** */
/* Main functions */
/* ************************************************************************** */
/**
* p7_send_buf:
* Send a buffer.
*
* @arg handle the libp7 handle
* @arg buf the buffer to send (NULL if normal buffer)
* @arg bufsize the buffer size
* @arg resp check response (is yes for 99.9% of the cases)
* @return if worked (0 if none)
*/
static int p7_send_buf(p7_handle_t *handle,
const unsigned char *buf, size_t bufsize, int resp)
{
/* check if handler is initialized */
if (!handle) return (p7_error_uninitialized);
/* check if user wants to shift
* with hack: if `buf` is non-NULL, we simply want to send custom packet */
if (!buf && !resp) {
if (handle->_flags & p7_intflag_shifted)
return (p7_error_doubleshift);
else handle->_flags |= p7_intflag_shifted;
}
/* get buffer */
if (!buf) {
buf = buffer;
bufsize = buffer_size;
}
/* sending loop */
int wasresend = 0, resp_err = 0;
do {
/* log resend request */
if (wasresend) {
if (handle->_flags & p7_intflag_shifted) switch_buffer();
buf = buffer; bufsize = buffer_size;
log_warn("resend request was received, resend it goes");
}
/* send prepared packet */
int err = p7_write(&handle->_stream, buf, bufsize);
if (err) return (err);
/* set wasreset for logging */
wasresend = 1;
} while (resp && ((resp_err = p7_recv(handle, 1))
|| (response.type == p7_pt_error && response.code == p7_err_resend)));
/* packet sending is finished */
return (resp_err);
}
/**
* p7_send_basic:
* Send a non-extended packet.
*
* @arg handle the libp7 handle
* @arg type the packet type
* @arg subtype the packet subtype
* @arg resp check response (is yes for 99.9% of the cases)
* @return if worked (0 if none)
*/
int p7_send_basic(p7_handle_t *handle,
p7_packettype_t type, p7ushort_t subtype, int resp)
{
/* change buffer and prepare packet */
switch_buffer();
buffer[0] = (unsigned char)type;
p7_putascii(&buffer[1], subtype, 2);
buffer[3] = '0';
p7_putascii(&buffer[4], p7_checksum(buffer, 6), 2);
buffer_size = 6;
/* log packet */
log_info("sending the following basic packet :");
logm_info(buffer, buffer_size);
/* send it */
int err = p7_send_buf(handle, NULL, 0, resp);
if (!err && type == p7_pt_term)
handle->_env = NULL;
if (!err && type == p7_pt_roleswp)
handle->_flags &= ~p7_intflag_active;
return (err);
}
/**
* p7_send_ext:
* Send an extended packet.
*
* @arg handle the libp7 handle
* @arg type the packet type
* @arg subtype the packet subtype
* @arg data the packet data
* @arg size the packet data size
* @arg resp check response (is yes for 99.9% of the cases)
* @return if it worked
*/
int p7_send_ext(p7_handle_t *handle,
p7_packettype_t type, p7ushort_t subtype,
const void *data, p7ushort_t size, int resp)
{
/* check if should be a binary zero at end of packet */
int binary_zero = (type == p7_pt_cmd && subtype == 0x56);
/* change buffer and prepare packet */
switch_buffer();
/* - first infos - */
buffer[0] = (unsigned char)type;
p7_putascii(&buffer[1], subtype, 2);
buffer[3] = '1';
/* - data - */
size = p7_encode(&buffer[8], data, size);
p7_putascii(&buffer[4], size, 4);
/* - checksum - */
p7_putascii(&buffer[8 + size], p7_checksum(buffer, 8 + size + 2), 2);
buffer_size = 8 + size + 2;
if (binary_zero) { buffer[buffer_size] = 0; buffer_size++; }
/* log packet */
log_info("sending the following extended packet :");
logm_info(buffer, buffer_size);
/* send it */
return (p7_send_buf(handle, NULL, 0, resp));
}
/**
* p7_send_again:
* Send the last packet again.
*
* Useful for when resending wasn't managed in one of the previous functions.
* Only used for unshifting right now.
*
* @arg handle the libp7 handle
* @return if it worked
*/
int p7_send_again(p7_handle_t *handle)
{
/* log packet */
log_info("sending again the following packet :");
logm_info(buffer, buffer_size);
/* send it */
return (p7_send_buf(handle, NULL, 0, 1));
}
/**
* p7_send_err_resend:
* Resend the resend error.
*/
int p7_send_err_resend(p7_handle_t *handle)
{
static const unsigned char resend_buf[] =
{p7_pt_error, '0', '1', '0', '6', 'F', 0};
/* send packet */
log_info("sending resend");
return (p7_send_buf(handle, resend_buf, 6, 0));
}
/**
* p7_send_check:
* Send a timeout check.
*/
int p7_send_check(p7_handle_t *handle)
{
static const unsigned char check_buf[] =
{p7_pt_check, '0', '1', '0', '6', 'F', 0};
/* send packet */
log_info("send check");
return (p7_send_buf(handle, check_buf, 6, 0));
}