Commit 8949fcd4 authored by Arnaud Blanchard's avatar Arnaud Blanchard

Initial files

parents
# Copyright ETIS — ENSEA, Université de Cergy-Pontoise, CNRS (2011 - 2016)
# Author: Arnaud Blanchard
# This software is governed by the CeCILL v2.1 license under French law and abiding by the rules of distribution of free software.
# You can use, modify and/ or redistribute the software under the terms of the CeCILL v2.1 license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info".
# As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license,
# users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability.
# In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software,
# that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge.
# Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured  and, more generally, to use and operate it in the same conditions as regards security.
# The fact that you are presently reading this means that you have had knowledge of the CeCILL v2.1 license and that you accept its terms.
cmake_minimum_required(VERSION 2.6)
project(blc_network)
add_definitions(-Wall -Wno-multichar -pthread)
#source files
set(sources
src/blc_network.cpp
src/blc_net_array.cpp
)
add_subdirectory(${BLAAR_DIR}/blc_core blc_core)
include_directories(${BL_INCLUDE_DIRS} include)
#shared lib
if (NOT TARGET blc_network)
add_library(blc_network SHARED ${sources})
target_link_libraries(blc_network ${BL_LIBRARIES})
if (UNIX AND NOT APPLE)
target_link_libraries(blc_network rt)
endif()
set(BL_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include ${BL_INCLUDE_DIRS} PARENT_SCOPE)
set(BL_LIBRARIES blc_network ${BL_LIBRARIES} PARENT_SCOPE)
install(TARGETS blc_network DESTINATION lib/blc)
endif()
#static lib
if (NOT TARGET static_blc_network)
add_library(static_blc_network STATIC ${sources})
#Both librairies have the same name. Only the extension will change depending on the OS
set_target_properties(static_blc_network PROPERTIES OUTPUT_NAME blc_network)
install(TARGETS static_blc_network DESTINATION lib/blc)
endif()
#Describe what will be to install or in the package by default the prefix (CMAKE_INSTALL_PREFIX) is '/usr/’
install(DIRECTORY include/ DESTINATION include/blc)
#Package
set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Arnaud Blanchard")
include(CPack)
#Add a target to generate documentation
if (NOT TARGET doc_${PROJECT_NAME})
find_package(Doxygen)
if(DOXYGEN_FOUND)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxyfile.in doxyfile.doxy) #Replace the CMAKE variables in the Doxyfile
add_custom_target(doc_${PROJECT_NAME} ALL ${DOXYGEN_EXECUTABLE} doxyfile.doxy COMMENT "Generating API documentation with Doxygen" VERBATIM )
else(DOXYGEN_FOUND)
message("You need to install doxygen to generate the doc.")
endif(DOXYGEN_FOUND)
endif()
PROJECT_NAME = ${PROJECT_NAME}
OPTIMIZE_OUTPUT_FOR_C = YES
EXTRACT_LOCAL_CLASSES = NO
HIDE_UNDOC_MEMBERS = YES
HIDE_UNDOC_CLASSES = YES
HIDE_FRIEND_COMPOUNDS = YES
HIDE_IN_BODY_DOCS = YES
CASE_SENSE_NAMES = NO
SORT_MEMBER_DOCS = NO
QUIET = YES
INPUT = ${CMAKE_CURRENT_SOURCE_DIR}
RECURSIVE = YES
USE_MDFILE_AS_MAINPAGE = ${CMAKE_CURRENT_SOURCE_DIR}/README.md
ALPHABETICAL_INDEX = NO
HTML_OUTPUT = html
LATEX_OUTPUT = latex
MACRO_EXPANSION = YES
PREDEFINED = __cplusplus = 1
REPEAT_BRIEF = YES
SKIP_FUNCTION_MACROS = NO
CLASS_DIAGRAMS = NO
//
// blc_net_array.h
//
// Created by Arnaud Blanchard on 01/11/2016.
//
//
/**
@defgroup blc_net_array
@{*/
#ifndef BLC_NET_ARRAY_H
#define BLC_NET_ARRAY_H
#include "blc_array.h"
#include "blc_network.h"
typedef struct blc_net_array
#ifdef __cplusplus
:blc_array{
void init_server( char const *service_name, char const *port_name, void (*callback)(blc_net_array *net_array, void*), void* callback_arg, uint32_t type, uint32_t format, int dims_nb, int length0, ...);
void init_client( char const *service_name, char const *address="localhost", char const *port_name="33333", int us_timeout=100000);
int try_recv_update(int us_timeout=100000);
void recv_update(int us_timeout = 100000, int trials_nb = 1);
void send_update();
void start_refresh_updates(void (*callback)(blc_net_array*, void *), void *arg, int refresh_period, int us_timeout, int trials_nb);
#else
{
blc_array array;
#endif
blc_network network;
char name[NAME_MAX];
int refresh_period;
pthread_t thread;
void (*callback)(blc_net_array*, void*);
void *callback_arg;
}blc_net_array;
START_EXTERN_C
END_EXTERN_C
#endif
///@}
\ No newline at end of file
//
// blc_network.h
// network
//
// Created by Arnaud Blanchard on 30/05/2015.
//
//
/**
@defgroup blc_network network
Few functions helping for pseudo realtime applications.
@{*/
#ifndef BLC_NETWORK_H
#define BLC_NETWORK_H
#include <stdio.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
#include "blc_mem.h"
/*By default it is a client*/
#define BLC_SERVER 1
#define BLC_UDP4 2
#define BLC_UDP4_SERVER (BLC_SERVER | BLC_UDP4)
#define BLC_NET_PROTOCOLE (BLC_UDP4) // FOr now it is use less but latter it will include all the protocoles
/* To be used with readv/writev, sendmsg/recvmsg. */
#define BLC_SET_IOVEC(iovec, variable) blc_set_iovec(iovec, &(variable), sizeof(variable), NULL)
#define BLC_SET_IOVEC2(iovec, variable1, variable2) blc_set_iovec(iovec, &(variable1), sizeof(variable1), &(variable2), sizeof(variable2), NULL)
#define BLC_SET_IOVEC3(iovec, variable1, variable2, variable3) blc_set_iovec(iovec, &(variable1), sizeof(variable1),&(variable2), sizeof(variable2),&(variable3), sizeof(variable3), NULL)
typedef struct blc_server blc_server;
//typedef void (*type_blc_server_callback)(blc_server *server);
typedef struct blc_network
#ifdef __cplusplus
:blc_mem{
/**Init a network connection in **mode** **BLC_UDP4** (udp IPv4) for now.
**address** can be null (usually for a server). Acceptable value for **address** is either a valid host name or a numeric host address string consisting of a dotted decimal IPv4
**port_name** is a port number as a string of a decimal number.
If buffer_size=0, you are responsible for allocating the memory in .data (use .allocate(size) for example).
*/
void init(char const *address_name, char const *port_name, int mode, size_t buffer_size=0);
void send();
void send_buffer(void const* data, size_t size);
void get_remote_address(char *channel_name, socklen_t name_size, char *port_name, socklen_t port_name_size);
void close();
void close_and_free_buffer();
#else
{ blc_mem mem;
#endif
struct sockaddr_storage remote_address;
socklen_t remote_address_length;
int socket_fd;
}blc_network;
typedef struct blc_server
#ifdef __cplusplus
:blc_network {
/** start a *pthread* with a server listenning (*rcvmsg*) in the **port_name** (i.e. "3333") with **mode** BLC_UDP4 (only for now).
Each time the server receive data on the associated port it will call the callback with the data received as parameter.
**.mem**, the receiving buffer has to be allocated before with enough size to store all a received message.
*/
void start(char const *port_name, int mode, void(*on_receive_data)(blc_server*) , void *arg, size_t buffer_size=0);
/**stop (close(socket_fd)) the server*/
void stop();
/** stop the server and free the allocated receive buffer*/
void stop_and_free_buffer();
void send_back();
void send_back_buffer(void const *buffer, size_t size);
#else
{ blc_network network;
#endif
pthread_t thread;
void(*callback)(blc_server*);
void *callback_arg;
}blc_server;
START_EXTERN_C
///Set a **iovev struct** used by sendmsg/recvmsg, with all the buffers (couples pointer/size) in the list. The list **has** to finish by **NULL**.
int blc_set_iovec(struct iovec *iov, void *data, size_t size, ...);
void blc_set_msghdr(struct msghdr *msghdr, void *data, size_t size, ...);
void blc_network_init(blc_network *network, char const *address_name, char const *port_name, int mode);
void blc_server_start(blc_server *server, char const *port_name, int mode, void(*on_receive_data)(blc_server*), void *);
void blc_server_allocate_mem_and_start(blc_server *server, char const *port_name, int mode, void(*on_receive_data)(blc_server*), void *, size_t size);
END_EXTERN_C
#endif
///@}
\ No newline at end of file
/* Basic Library for C/C++ (blclib)
Copyright ETIS — ENSEA, Université de Cergy-Pontoise, CNRS (2011 - 2016)
Author: A. Blanchard
This software is a computer program whose purpose is to simulate neural networks and control robots or simulations.
This software is governed by the CeCILL v2.1 license under French law and abiding by the rules of distribution of free software.
You can use, modify and/ or redistribute the software under the terms of the CeCILL v2.1 license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info".
As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license,
 users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability.
 In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software,
 that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge.
Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured
 and, more generally, to use and operate it in the same conditions as regards security.
 The fact that you are presently reading this means that you have had knowledge of the CeCILL v2.1 license and that you accept its terms. */
//
// Created by Arnaud Blanchard on 01/11/2016.
//
#include "blc_net_array.h"
#include "blc_realtime.h"
#include "blc_text.h"
#include <sys/select.h> //select
#include <unistd.h> //read
static blc_net_array **net_arrays=NULL;
static int net_arrays_nb=0;
static void *net_array_update_manager(void *user_data){
blc_net_array *net_array = (blc_net_array*)user_data;
fd_set fdset;
ssize_t ret;
struct timeval timeout={0, 100000}; //100ms
//Wait for data to be ready
FD_ZERO(&fdset);
while(1){
FD_SET(net_array->network.socket_fd, &fdset);
SYSTEM_ERROR_CHECK(ret=select(net_array->network.socket_fd+1, &fdset, NULL, NULL, &timeout), -1, "Waiting server channel data"); //It would be nice to check errorfds
if (ret==0) printf("Timeout for server\n");
else{
SYSTEM_ERROR_CHECK(ret=read(net_array->network.socket_fd, net_array->data, net_array->size), -1, NULL);
if (ret != (ssize_t)net_array->size) EXIT_ON_ERROR("Reading data: '%lu' bytes instead of '%lu'", ret, net_array->size);
}
}
}
static void *refresh_server_cb(void *user_data){
// struct timespec time_left={0,0};
struct timeval timer={0, 0};
blc_net_array *net_array = (blc_net_array*)user_data;
int current_duration;
int64_t time_left;
char buffer[1024];
int32_t refresh_period=-1;
char address_name[NAME_MAX], port_name[NAME_MAX];
ssize_t bytes_nb;
net_array->sprint_properties(buffer, 1024);
net_array->network.send_buffer(buffer, 1024);
if (refresh_period==-2){
while(1){
SYSTEM_ERROR_CHECK(bytes_nb=read(net_array->network.socket_fd, net_array->data, net_array->size), -1, NULL);
if (bytes_nb!=(ssize_t)net_array->size) EXIT_ON_ARRAY_ERROR(net_array, "Read only '%d' bytes instead of %d.", bytes_nb, net_array->size);
}
}
else {
while(1){
net_array->network.send_buffer(net_array->data, net_array->size);
if (refresh_period){
if (refresh_period==-1){
read(net_array->network.socket_fd, &refresh_period, sizeof(refresh_period));
}else if (refresh_period==-2)
{
break;
}else{
current_duration=us_time_diff(&timer);
time_left = (net_array->refresh_period - current_duration);
if (time_left < 0) color_fprintf(BLC_YELLOW, stderr, "\rMissing %.3fms to send the channel.", -time_left/1000.f);
else SYSTEM_SUCCESS_CHECK(usleep(time_left), 0, "Program loop interrupted");
current_duration=us_time_diff(&timer);
/*Warning usleep can be overtimed of 10ms !!! it is the same for usleep !!!*/
}
}
}
}
return NULL;
}
/** It is called each time the port 33333 receive a message. If it is a known channel, a new port is opened specifically for the channel*/
static void net_array_request_cb(blc_server *server){
int error;
struct sockaddr_storage address;
socklen_t address_size;
blc_net_array **tmp_array, *found_net_array=NULL;
int32_t refresh_rate;
refresh_rate=server->ints32[0];
FOR_EACH(tmp_array, net_arrays, net_arrays_nb) if (strncmp((*tmp_array)->name, server->chars+sizeof(int32_t), server->size)==0){
found_net_array=*tmp_array;
break;
}
SYSTEM_ERROR_CHECK(getsockname(server->socket_fd, (struct sockaddr*)&address, &address_size), -1, NULL);
if (found_net_array){
found_net_array->network.init(server->chars, "0", BLC_UDP4 | BLC_SERVER);
SYSTEM_ERROR_CHECK(getsockname(found_net_array->network.socket_fd, (struct sockaddr*)&address, &address_size), -1, NULL);
found_net_array->network.remote_address=server->remote_address;
found_net_array->network.remote_address_length=server->remote_address_length;
PTHREAD_CHECK(pthread_create(&found_net_array->thread, NULL, refresh_server_cb, found_net_array), error, "Creating refresh cb");
}
else{
snprintf(server->chars, server->size, "error: blc_net_channel does not exist.\n");
server->send_back();
}
}
void blc_net_array::init_server( char const *service_name, char const *port_name, void (*callback)(blc_net_array *net_array, void*), void* callback_arg, uint32_t type, uint32_t format, int dims_nb, int length0, ...){
blc_net_array *this_pt=this;
va_list arguments;
va_start(arguments, length0);
blc_array::vdef_array(type, format, dims_nb, length0, arguments);
va_end(arguments);
STRCPY(name, service_name);
this->callback=callback;
this->callback_arg=callback_arg;
APPEND_ITEM(&net_arrays, &net_arrays_nb, &this_pt);
}
void blc_net_array::init_client(char const *service_name, char const *address, char const *port_name, int us_timeout){
char buffer[LINE_MAX];
fd_set fdset;
int ret;
struct timeval timeout={0, us_timeout}; //100ms
network.init(address, port_name, BLC_UDP4);
//Send channel name request
network.send_buffer(service_name, strlen(service_name));
//Wait for data to be ready
FD_ZERO(&fdset);
FD_SET(network.socket_fd, &fdset);
SYSTEM_ERROR_CHECK(ret=select(network.socket_fd+1, &fdset, NULL, NULL, &timeout), -1, "Waiting server channel definition"); //It would be nice to check errorfds
if (ret==0) EXIT_ON_ERROR("Timeout of %.3fms. The server is probably down.", timeout.tv_sec*1000 + timeout.tv_usec/1000.f);
network.remote_address_length=sizeof(network.remote_address);
//Get the propoerties of the channel and the address (especilly the new port) of the sender
SYSTEM_ERROR_CHECK(ret=recvfrom(network.socket_fd, buffer, LINE_MAX, NO_FLAG, (struct sockaddr*)&network.remote_address, &network.remote_address_length), -1, "Reading blc_channel properties");
if (ret == LINE_MAX) EXIT_ON_ERROR("Buffer of '%d' is too small", ret);
blc_array::init(buffer);
allocate();
}
int blc_net_array::try_recv_update(int us_timeout){
ssize_t ret;
fd_set fdset;
struct timeval timeout={0, us_timeout};
FD_ZERO(&fdset);
FD_SET(network.socket_fd, &fdset);
network.send_buffer(&refresh_period, sizeof(refresh_period));
SYSTEM_ERROR_CHECK(ret=select(network.socket_fd+1, &fdset, NULL, NULL, &timeout), -1, "Waiting server channel data"); //It would be nice to check errorfds
if (ret==0) return 0; //Timeout
SYSTEM_ERROR_CHECK(ret=read(network.socket_fd, data, size), -1, NULL);
if (ret!=(ssize_t)size)EXIT_ON_ERROR("Reading data: '%lu' bytes instead of '%lu'", ret, size);
return 1;
}
void blc_net_array::recv_update(int us_timeout, int trials_nb){
int i;
FOR_INV(i, trials_nb) if (try_recv_update(us_timeout) == 1) return;
EXIT_ON_ARRAY_ERROR(this, "Impossible to receive data in '%d' µs", us_timeout);
}
void blc_net_array::send_update(){
network.send_buffer(data, size);
}
void blc_net_array::start_refresh_updates(void (*callback)(blc_net_array*, void *), void *arg, int refresh_period, int us_timeout, int trials_nb){
int i;
int error;
this->callback=callback;
this->callback_arg=arg;
this->refresh_period = refresh_period;
FOR_INV(i, trials_nb) if (try_recv_update(us_timeout) == 1) return;
EXIT_ON_ARRAY_ERROR(this, "Impossible to receive data in '%d' µs. Stop after '%d' trials.", us_timeout, trials_nb);
PTHREAD_CHECK(pthread_create(&thread, NULL, net_array_update_manager, this), error, NULL);
}
void blc_net_array_start_server(char const* port_name){
blc_server server;
server.start(port_name, BLC_UDP4, net_array_request_cb, NULL, LINE_MAX);
}
//
// blc_network.cpp
// network
//
// Created by Arnaud Blanchard on 30/05/2015.
//
//
#include "blc_network.h"
#include "blc_mem.h"
#include "blc_realtime.h"
#include <unistd.h>
#include <pthread.h>
#include <netdb.h>
#include <sys/types.h>
static void* server_manager(void *arg)
{
blc_server *server=(blc_server*)arg;
ssize_t received_data_size;
if (server->data==NULL) EXIT_ON_ERROR("You have not allocated the receive buffer");
server->remote_address_length=sizeof(struct sockaddr_storage);
while(1) //pthread_cancel is used to stop it
{
//What if bufffer is too small ?
SYSTEM_ERROR_CHECK(received_data_size = recvfrom(server->socket_fd, server->data, server->size, 0, (struct sockaddr*)&server->remote_address, &server->remote_address_length), -1, "Error receiving data.");
server->callback(server);
}
return NULL;
}
static int blc_vset_iovec(struct iovec *iov, void *data, size_t size, va_list arguments){
int len;
for(len=0; data != NULL; len++)
{
iov[len].iov_base = data;
iov[len].iov_len = size;
data = va_arg(arguments, void*);
size = va_arg(arguments, size_t);
}
return len;
}
int blc_set_iovec(struct iovec *iovec, void *data, size_t size, ...)
{
int len;
va_list arguments;
va_start(arguments, size);
len = blc_vset_iovec(iovec, data, size, arguments);
va_end(arguments);
return len;
}
void blc_set_msghdr(struct msghdr *msghdr, void *data, size_t size, ...)
{
va_list arguments;
va_start(arguments, size);
msghdr->msg_iovlen=blc_vset_iovec(msghdr->msg_iov, data, size, arguments);
va_end(arguments);
}
/* In the default case (client) we do not use connect to be able to read response from the server*/
void blc_network::init(char const *address_name, char const *port_name, int mode, size_t buffer_size){
struct addrinfo hints, *results;
int ret;
struct sockaddr_storage address;
socklen_t address_size;
CLEAR(hints);
hints.ai_flags = AI_NUMERICSERV; //We use only port number not service name ( faster )
if (mode & BLC_SERVER) hints.ai_flags|= AI_PASSIVE; // if address is NULL it is ANY_ADDR otherwise. If not server it is loopback (~localhost)
switch (mode & BLC_NET_PROTOCOLE){
case BLC_UDP4:
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_DGRAM;
break;
default:
EXIT_ON_ERROR("Unknown mode %d. The possibility is 'BLC_UDP4'.", mode);
break;
}
ret=getaddrinfo(address_name, port_name, &hints, &results);
if (ret !=0) EXIT_ON_ERROR(gai_strerror(ret)); //, 0, "setting address: %s", address_name));
if(results->ai_next != NULL) EXIT_ON_ERROR("There is more than one possible address. It is not yet implemented.");
SYSTEM_ERROR_CHECK(socket_fd = socket(results->ai_family, results->ai_socktype, results->ai_protocol), -1, NULL); //We suppose there is only one result in 'results'
address_size = sizeof(address);
SYSTEM_ERROR_CHECK(getsockname(socket_fd, (struct sockaddr*)&address, &address_size), -1, NULL);
if (mode & BLC_SERVER) SYSTEM_ERROR_CHECK(bind(socket_fd, results->ai_addr, results->ai_addrlen), -1, "Socket %d", socket_fd);
else { //We do not use connect to allow the port to also read answers
memcpy(&remote_address, (void*)results->ai_addr, results->ai_addrlen);
remote_address_length=results->ai_addrlen;
}
freeaddrinfo(results);
if (buffer_size) allocate(buffer_size);
}
void blc_network::get_remote_address(char *channel_name, socklen_t name_size, char *port_name, socklen_t port_name_size){
int ret;
ret=getnameinfo((const struct sockaddr *)&remote_address, remote_address_length, channel_name, name_size, port_name, port_name_size, NI_NUMERICSERV);
if (ret !=0) EXIT_ON_ERROR(gai_strerror(ret)); //, 0, "setting address: %s", address_name));
}
void blc_network::send(){
if (this->data==NULL) EXIT_ON_ERROR("You have not allocated buffer.");
SYSTEM_ERROR_CHECK(sendto(socket_fd, this->data, this->size, 0, (struct sockaddr*)&remote_address, remote_address_length), -1, "socket_fd '%d', request first size '%lu'", socket_fd, remote_address_length);
}
void blc_network::send_buffer(void const* buffer, size_t size){
ssize_t ret;
SYSTEM_ERROR_CHECK(ret=sendto(socket_fd, buffer, size, NO_FLAG, (struct sockaddr*)&remote_address, remote_address_length), -1, "socket_fd '%d', request size '%u'", socket_fd, size);
if ((size_t)ret!=size) EXIT_ON_ERROR("Only '%l' bytes sent instead of '%lu'", ret, size);
}
void blc_network::close(){
::close(socket_fd);
}
void blc_network::close_and_free_buffer(){
this->close();
this->free();
}
void blc_server::start(char const *port_name, int protocol, void(*on_receive_data)(blc_server*), void *arg, size_t buffer_size){
callback = on_receive_data;
callback_arg = arg;
init(NULL, port_name, protocol | BLC_SERVER, buffer_size);
SYSTEM_SUCCESS_CHECK(pthread_create(&thread, NULL, server_manager, (void*)this), 0, "Starting server");
}
void blc_server::stop(){
int error;
callback = NULL;
callback_arg = NULL;
PTHREAD_CHECK(pthread_cancel(thread), error, NULL);
/*We wait that the thread has stopped before closing the socket*/
PTHREAD_CHECK(pthread_join(thread, NULL), error, NULL);
::close(socket_fd);
}
void blc_server::stop_and_free_buffer(){
stop();
free();
}
void blc_server::send_back(){
SYSTEM_ERROR_CHECK(sendto(socket_fd, data, size , NO_FLAG, (struct sockaddr*)&remote_address, remote_address_length), -1, "socket %d", socket_fd);
}
void blc_server::send_back_buffer(void const *buffer, size_t buffer_size){
// printf("%s\n", (char*)buffer);
SYSTEM_ERROR_CHECK(sendto(socket_fd, buffer, buffer_size , NO_FLAG, (struct sockaddr*)&remote_address, remote_address_length), -1, "socket %d", socket_fd);
}
/* Network */
START_EXTERN_C
void blc_network_init(blc_network *network, char const *address_name, char const *port_name, int mode){
network->init(address_name, port_name, mode);
}
void blc_server_start(blc_server *server, char const *port_name, int mode, void(*on_receive_data)(blc_server*), void *arg){
server->start(port_name, mode, on_receive_data, arg);
}
void blc_server_allocate_mem_and_start(blc_server *server, char const *port_name, int mode, void(*on_receive_data)(blc_server*), void *arg, size_t buffer_size){
server->start(port_name, mode, on_receive_data, arg, buffer_size);
}
END_EXTERN_C
# Copyright ETIS — ENSEA, Université de Cergy-Pontoise, CNRS (2011 - 2016)
# Author: Arnaud Blanchard
# This software is governed by the CeCILL v2.1 license under French law and abiding by the rules of distribution of free software.
# You can use, modify and/ or redistribute the software under the terms of the CeCILL v2.1 license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info".
# As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license,
# users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability.
# In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software,
# that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge.
# Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured  and, more generally, to use and operate it in the same conditions as regards security.
# The fact that you are presently reading this means that you have had knowledge of the CeCILL v2.1 license and that you accept its terms.
cmake_minimum_required(VERSION 2.6)
project(t_net_array_client)
add_definitions(-Wall -Wno-multichar)
add_subdirectory(${BLAAR_DIR}/blc_core blc_core)
add_subdirectory(${BLAAR_DIR}/blc_network blc_network)
include_directories(${BL_INCLUDE_DIRS})
message("${BL_LIBRARIES}")
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} ${BL_LIBRARIES})
/* Author: Arnaud Blanchard
Example to demonstrate how to use blc_network.
*/
#include "blc_net_array.h"
#include <sys/time.h>
#define SIZE 1024
int main(int, char **){
blc_net_array array_to_recv, array_to_send;
blc_server server;
fprintf(stderr, "\nExample of a program sending blc_array in udp on port '3333'\n'q' to quit\n");
array_to_send.def_array('UIN8', 'NDEF', 2, 3, 3);
array_to_send.allocate();
array_to_send.chars[0]=1;
array_to_send.send("localhost", "33333");
// array_to_send.send_updates();
while(getchar()!='q');
server.stop_and_free_buffer();
return EXIT_SUCCESS;
}
\ No newline at end of file
# Copyright ETIS — ENSEA, Université de Cergy-Pontoise, CNRS (2011 - 2016)
# Author: Arnaud Blanchard
# This software is governed by the CeCILL v2.1 license under French law and abiding by the rules of distribution of free software.
# You can use, modify and/ or redistribute the software under the terms of the CeCILL v2.1 license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info".
# As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license,
# users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability.
# In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software,
# that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge.
# Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured  and, more generally, to use and operate it in the same conditions as regards security.
# The fact that you are presently reading this means that you have had knowledge of the CeCILL v2.1 license and that you accept its terms.
cmake_minimum_required(VERSION 2.6)
project(t_net_array_server)
add_definitions(-Wall -Wno-multichar)
add_subdirectory(${BLAAR_DIR}/blc_core blc_core)
add_subdirectory(${BLAAR_DIR}/blc_network blc_network)
include_directories(${BL_INCLUDE_DIRS})