217 lines
6.0 KiB
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));
|
|
}
|