libp7/src/core/_init.c

219 lines
5.9 KiB
C

/* ************************************************************************** */
/* _____ _ */
/* core/_init.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libp7 | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2017/01/04 15:01:48 |___/ */
/* */
/* ************************************************************************** */
#include <libp7/internals.h>
#include <stdlib.h>
#include <string.h>
/* simple global containing handle size */
const size_t p7_handle_size = sizeof(p7_handle_t);
/* ************************************************************************** */
/* Get and set handler data */
/* ************************************************************************** */
/**
* p7_get_response:
* Get response from handle.
*
* The handle has an unknown structure for the user.
*
* @arg handle the handle.
* @return the stream.
*/
const p7_packet_t *p7_get_response(p7_handle_t *handle)
{
return (handle->_response);
}
/**
* p7_get_stream:
* Get stream from handle.
*
* Same reason than above.
*
* @arg handle the handle.
* @return the stream.
*/
const p7_stream_t *p7_get_stream(p7_handle_t *handle)
{
return (handle->_stream);
}
/**
* p7_get_info:
* Get server info.
*
* @arg handle the handle.
* @return the server info.
*/
const p7_server_t *p7_get_info(p7_handle_t *handle)
{
return (&handle->_server);
}
/* ************************************************************************** */
/* Initialization */
/* ************************************************************************** */
/**
* start:
* Start the communication.
*
* @arg handle the handle.
* @return the error, if any.
*/
static int start(p7_handle_t *handle, int check)
{
int err = 0;
log_info("so we're active? let's do what active people do then!");
/* send initial check */
if (check) {
log_info("sending initial check packet");
if ((err = p7_send_ini_check(handle))) {
log_fatal("couldn't send check/didn't receive answer");
return (err);
} else if (response.type != p7_pt_ack) {
log_fatal("received packet wasn't ack, ask your dentist");
return (p7_error_unknown);
}
#if LOGLEVEL <= ll_info
} else {
log_info("skipping initial check, we suppose already initialized");
#endif
}
/* discover environment */
log_info("checkin' up da environment");
if ((err = p7_send_cmdsys_getinfo(handle))) {
log_fatal("couldn't send env query/receive answer");
return (err);
} else if (response.type != p7_pt_ack || !response.extended) {
log_fatal("response to env query wasn't an extended ack packet");
return (p7_error_unknown);
}
/* save server */
handle->_server = response.info;
/* get environment based on sent hardware id */
handle->_env = p7_get_env(handle->_server.hwid);
log_info("environment is '%s'", handle->_env->name);
/* no error */
return (0);
}
/**
* p7_sinit:
* Initialize libp7 with a P7 stream.
*
* @arg h the handle to create
* @arg flags the flags.
* @arg name the name of the handle.
* @arg dstream the P7 stream to use.
* @return the error (0 if ok)
*/
int p7_sinit(p7_handle_t **h, unsigned int flags,
const char *name, p7_stream_t dstream)
{
int err = 0;
/* allocate handle */
int alloc = !*h;
if (alloc) {
logr_info("looks like the handle wasn't allocated! let's make one.");
*h = NULL;
if (!(*h = malloc(sizeof(p7_handle_t))))
return (p7_error_alloc);
}
/* initialize handle */
p7_handle_t *handle = *h;
memset(handle, 0, sizeof(p7_handle_t));
handle->_wasalloc = alloc;
handle->_stream_data = dstream;
handle->_stream = &handle->_stream_data;
handle->_response = &handle->_response_data;
/* prepare the name */
if (!name) handle->_name[0] = 0;
else {
handle->_name[0] = ' ';
strncpy(&handle->_name[1], name, 8);
handle->_name[9] = 0;
}
log_info("handle prepared, masta!");
/* set the initial communication settings */
log_info("initializing stream settings");
p7_setcomm(handle->_stream, P7_B9600, P7_PARITY_NONE, P7_TWOSTOPBITS);
/* starting as active */
handle->_active = flags & P7_ACTIVE;
handle->_terminated = 0;
handle->_term = flags & P7_TERM;
/* initialize environment */
handle->_env = NULL;
/* initialize stupid things */
handle->_shifted = 0;
handle->_send_buffers_size[0] = 0;
handle->_send_buffers_size[1] = 0;
handle->_send_buffer_id = 0;
/* if active, start */
if (handle->_active && (err = start(handle, flags & P7_CHECK))) {
handle->_term = P7_TERM;
p7_exit(*h); *h = NULL;
return (err);
}
/* initialization went alright */
return (0);
}
/* ************************************************************************** */
/* De-initialization */
/* ************************************************************************** */
/**
* p7_exit:
* De-initialize libp7.
*
* @arg handle the handle to free.
* @arg wasalloc should we free the handle?
*/
void p7_exit(p7_handle_t *handle)
{
log_info("exit is called.");
/* check if handle is already freed */
if (!handle) return;
log_info("and handle is still there, so let's go!");
/* terminate communication */
if (handle->_active && !handle->_terminated && handle->_term) {
log_info("we were active, send sending terminate packet");
if (p7_send_term(handle)) {
log_warn("couldn't send terminate packet, already disconnected?");
}
/* don't bother checking ack */
}
/* close stream */
(*handle->_stream->close)(handle->_stream->cookie);
/* free handle */
log_info("freeing the handle!");
if (handle->_wasalloc) free(handle);
}