| @@ -0,0 +1,432 @@ | |||
| /* | |||
| Copyright (C) 2016-2019 Christoph Kuhr | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (at your option) any later version. | |||
| This program 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 General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #include "JackAVBDriver.h" | |||
| #include "JackEngineControl.h" | |||
| #include "JackLockedEngine.h" | |||
| #include "JackGraphManager.h" | |||
| #include "JackWaitThreadedDriver.h" | |||
| #include "JackTools.h" | |||
| #include "driver_interface.h" | |||
| #include "avb.h" | |||
| #define MIN(x,y) ((x)<(y) ? (x) : (y)) | |||
| using namespace std; | |||
| /* | |||
| * "enp4s0" | |||
| */ | |||
| namespace Jack | |||
| { | |||
| JackAVBDriver::JackAVBDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, | |||
| char* stream_id, char* destination_mac, char* eth_dev, | |||
| int sample_rate, int period_size, int adjust, int num_periods, int capture_ports, int playback_ports) | |||
| : JackWaiterDriver(name, alias, engine, table) | |||
| { | |||
| jack_log("JackAVBDriver::JackAVBPDriver Ethernet Device %s", eth_dev); | |||
| jack_log("Stream ID: %02x %02x %02x %02x %02x %02x %02x %02x", | |||
| (uint8_t) stream_id[0], | |||
| (uint8_t) stream_id[1], | |||
| (uint8_t) stream_id[2], | |||
| (uint8_t) stream_id[3], | |||
| (uint8_t) stream_id[4], | |||
| (uint8_t) stream_id[5], | |||
| (uint8_t) stream_id[6], | |||
| (uint8_t) stream_id[7]); | |||
| jack_log("Destination MAC Address: %02x:%02x:%02x:%02x:%02x:%02x", | |||
| (uint8_t) destination_mac[0], | |||
| (uint8_t) destination_mac[1], | |||
| (uint8_t) destination_mac[2], | |||
| (uint8_t) destination_mac[3], | |||
| (uint8_t) destination_mac[4], | |||
| (uint8_t) destination_mac[5]); | |||
| printf("JackAVBDriver::JackAVBPDriver Ethernet Device %s\n", eth_dev); | |||
| printf("Stream ID: %02x %02x %02x %02x %02x %02x %02x %02x\n", | |||
| (uint8_t) stream_id[0], | |||
| (uint8_t) stream_id[1], | |||
| (uint8_t) stream_id[2], | |||
| (uint8_t) stream_id[3], | |||
| (uint8_t) stream_id[4], | |||
| (uint8_t) stream_id[5], | |||
| (uint8_t) stream_id[6], | |||
| (uint8_t) stream_id[7]); | |||
| printf("Destination MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", | |||
| (uint8_t) destination_mac[0], | |||
| (uint8_t) destination_mac[1], | |||
| (uint8_t) destination_mac[2], | |||
| (uint8_t) destination_mac[3], | |||
| (uint8_t) destination_mac[4], | |||
| (uint8_t) destination_mac[5]); | |||
| num_packets_even_odd = 0; // even = 0, odd = 1 | |||
| init_avb_driver( &(this->avb_ctx), | |||
| eth_dev, | |||
| stream_id, | |||
| destination_mac, | |||
| sample_rate, | |||
| period_size, | |||
| num_periods, | |||
| adjust, | |||
| capture_ports, | |||
| playback_ports | |||
| ); | |||
| } | |||
| JackAVBDriver::~JackAVBDriver() | |||
| { | |||
| // No destructor yet. | |||
| } | |||
| //open, close, attach and detach------------------------------------------------------ | |||
| int JackAVBDriver::Close() | |||
| { | |||
| // Generic audio driver close | |||
| int res = JackWaiterDriver::Close(); | |||
| FreePorts(); | |||
| shutdown_avb_driver(&avb_ctx); | |||
| return res; | |||
| } | |||
| int JackAVBDriver::AllocPorts() | |||
| { | |||
| jack_port_id_t port_index; | |||
| char buf[64]; | |||
| int chn = 0; | |||
| for (chn = 0; chn < (int)avb_ctx.capture_channels; chn++) { | |||
| memset(buf, 0, sizeof(buf)); | |||
| snprintf (buf, sizeof(buf) - 1, "system:capture_%u", chn + 1); | |||
| if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE, | |||
| CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { | |||
| jack_error("driver: cannot register port for %s", buf); | |||
| return -1; | |||
| } | |||
| avb_ctx.capture_ports = jack_slist_append (avb_ctx.capture_ports, (void *)(intptr_t)port_index); | |||
| } | |||
| for (chn = 0; chn < (int)avb_ctx.playback_channels; chn++) { | |||
| memset(buf, 0, sizeof(buf)); | |||
| snprintf (buf, sizeof(buf) - 1, "system:playback_%u", chn + 1); | |||
| if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE, | |||
| PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { | |||
| jack_error("driver: cannot register port for %s", buf); | |||
| return -1; | |||
| } | |||
| avb_ctx.playback_ports = jack_slist_append (avb_ctx.playback_ports, (void *)(intptr_t)port_index); | |||
| } | |||
| //port = fGraphManager->GetPort(port_index); | |||
| return 0; | |||
| } | |||
| //init and restart-------------------------------------------------------------------- | |||
| bool JackAVBDriver::Initialize() | |||
| { | |||
| jack_log("JackAVBDriver::Init"); | |||
| FreePorts(); | |||
| //display some additional infos | |||
| printf("AVB driver started\n"); | |||
| if (startup_avb_driver(&avb_ctx)) { | |||
| return false; | |||
| } | |||
| //register jack ports | |||
| if (AllocPorts() != 0) { | |||
| jack_error("Can't allocate ports."); | |||
| return false; | |||
| } | |||
| //monitor | |||
| //driver parametering | |||
| JackTimedDriver::SetBufferSize(avb_ctx.period_size); | |||
| JackTimedDriver::SetSampleRate(avb_ctx.sample_rate); | |||
| JackDriver::NotifyBufferSize(avb_ctx.period_size); | |||
| JackDriver::NotifySampleRate(avb_ctx.sample_rate); | |||
| return true; | |||
| } | |||
| //jack ports and buffers-------------------------------------------------------------- | |||
| //driver processes-------------------------------------------------------------------- | |||
| int JackAVBDriver::Read() | |||
| { | |||
| int ret = 0; | |||
| JSList *node = avb_ctx.capture_ports; | |||
| uint64_t cumulative_rx_int_ns = 0; | |||
| int n = 0; | |||
| for(n=0; n<avb_ctx.num_packets; n++){ | |||
| cumulative_rx_int_ns += await_avtp_rx_ts( &avb_ctx, n ); | |||
| // jack_log("duration: %lld", cumulative_rx_int_ns); | |||
| } | |||
| float cumulative_rx_int_us = cumulative_rx_int_ns / 1000; | |||
| if ( cumulative_rx_int_us > avb_ctx.period_usecs) { | |||
| ret = 1; | |||
| NotifyXRun(fBeginDateUst, cumulative_rx_int_us); | |||
| jack_error("netxruns... duration: %fms", cumulative_rx_int_us / 1000); | |||
| } | |||
| JackDriver::CycleTakeBeginTime(); | |||
| if ( ret ) { | |||
| return -1; | |||
| } | |||
| while (node != NULL) { | |||
| jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data; | |||
| JackPort *port = fGraphManager->GetPort(port_index); | |||
| jack_default_audio_sample_t* buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize); | |||
| //memcpy(buf, 0, avb_ctx.period_size * sizeof(jack_default_audio_sample_t)); | |||
| node = jack_slist_next (node); | |||
| } | |||
| return 0; | |||
| } | |||
| int JackAVBDriver::Write() | |||
| { | |||
| JSList *node = avb_ctx.playback_ports; | |||
| while (node != NULL) { | |||
| jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data; | |||
| JackPort *port = fGraphManager->GetPort(port_index); | |||
| jack_default_audio_sample_t* buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize); | |||
| //memcpy(buf, 0, avb_ctx.period_size * sizeof(jack_default_audio_sample_t)); | |||
| node = jack_slist_next (node); | |||
| } | |||
| return 0; | |||
| } | |||
| void | |||
| JackAVBDriver::FreePorts () | |||
| { | |||
| JSList *node = avb_ctx.capture_ports; | |||
| while (node != NULL) { | |||
| JSList *this_node = node; | |||
| jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data; | |||
| node = jack_slist_remove_link(node, this_node); | |||
| jack_slist_free_1(this_node); | |||
| fEngine->PortUnRegister(fClientControl.fRefNum, port_index); | |||
| } | |||
| avb_ctx.capture_ports = NULL; | |||
| node = avb_ctx.playback_ports; | |||
| while (node != NULL) { | |||
| JSList *this_node = node; | |||
| jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data; | |||
| node = jack_slist_remove_link(node, this_node); | |||
| jack_slist_free_1(this_node); | |||
| fEngine->PortUnRegister(fClientControl.fRefNum, port_index); | |||
| } | |||
| avb_ctx.playback_ports = NULL; | |||
| } | |||
| //driver loader----------------------------------------------------------------------- | |||
| #ifdef __cplusplus | |||
| extern "C" | |||
| { | |||
| #endif | |||
| inline int argumentsSplitDelimiters(char* inputString, char* outputArray, int array_len) | |||
| { | |||
| int tokenCnt=0; | |||
| char *token; | |||
| char *der_string = strdup(inputString); | |||
| for(int m=0;m<array_len;m++){ | |||
| if(( token = strsep(&der_string, ":")) != NULL ){ | |||
| outputArray[m] = (char)strtol(strdup(token), NULL, 16); // number base 16 | |||
| } else { | |||
| tokenCnt = m; | |||
| break; | |||
| } | |||
| } | |||
| free(der_string); | |||
| return tokenCnt; | |||
| } | |||
| SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor () | |||
| { | |||
| jack_driver_desc_t * desc; | |||
| jack_driver_desc_filler_t filler; | |||
| jack_driver_param_value_t value; | |||
| desc = jack_driver_descriptor_construct("avb", JackDriverMaster, "IEEE 1722 AVTP slave backend component", &filler); | |||
| value.ui = 2U; | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "audio-ins", 'i', JackDriverParamUInt, &value, NULL, "Number of capture channels (defaults to 1)", NULL); | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "audio-outs", 'o', JackDriverParamUInt, &value, NULL, "Number of playback channels (defaults to 1)", NULL); | |||
| value.ui = 48000U; | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL); | |||
| value.ui = 64U; | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL); | |||
| value.ui = 1U; | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "num-periods", 'n', JackDriverParamUInt, &value, NULL, "Network latency setting in no. of periods", NULL); | |||
| value.ui = 0U; | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "adjust", 'a', JackDriverParamUInt, &value, NULL, "Adjust Timestamps", NULL); | |||
| sprintf( value.str, "enp4s0"); | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "eth-dev", 'e', JackDriverParamString, &value, NULL, "AVB Ethernet Device", NULL); | |||
| sprintf( value.str, "00:22:97:00:41:2c:00:00"); | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "stream-id", 's', JackDriverParamString, &value, NULL, "Stream ID for listening", NULL); | |||
| sprintf( value.str, "91:e0:f0:11:11:11"); | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "dst-mac", 'm', JackDriverParamString, &value, NULL, "Multicast Destination MAC Address for listening", NULL); | |||
| return desc; | |||
| } | |||
| SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) | |||
| { | |||
| unsigned int sample_rate = 48000; | |||
| jack_nframes_t period_size = 64; | |||
| unsigned int capture_ports = 2; | |||
| unsigned int playback_ports = 2; | |||
| int num_periods = 2; | |||
| int adjust = 0; | |||
| char sid[8]; | |||
| char dmac[6]; | |||
| char eth_dev[32]; | |||
| const JSList * node; | |||
| const jack_driver_param_t * param; | |||
| printf("foo bar\n");fflush(stdout); | |||
| for (node = params; node; node = jack_slist_next(node)) { | |||
| param = (const jack_driver_param_t*) node->data; | |||
| switch (param->character) { | |||
| case 'i': | |||
| capture_ports = param->value.ui; | |||
| break; | |||
| case 'o': | |||
| playback_ports = param->value.ui; | |||
| break; | |||
| case 'r': | |||
| sample_rate = param->value.ui; | |||
| break; | |||
| case 'p': | |||
| period_size = param->value.ui; | |||
| break; | |||
| case 'n': | |||
| num_periods = param->value.ui; | |||
| break; | |||
| case 'a': | |||
| adjust = param->value.ui; | |||
| break; | |||
| case 'e': | |||
| sprintf(eth_dev, "%s", param->value.str); | |||
| printf("Eth Dev: %s %s\n", param->value.str, eth_dev);fflush(stdout); | |||
| break; | |||
| case 's': | |||
| // split stream ID | |||
| argumentsSplitDelimiters((char *)param->value.str, sid, 8); | |||
| printf("Stream ID: %s %02x %02x %02x %02x %02x %02x %02x %02x \n", param->value.str, | |||
| sid[0], sid[1], sid[2], sid[3], sid[4], sid[5], sid[6], sid[7]);fflush(stdout); | |||
| break; | |||
| case 'm': | |||
| // split destination mac address | |||
| argumentsSplitDelimiters((char *)param->value.str, dmac, 6); | |||
| printf("Destination MAC Address: %s %02x %02x %02x %02x %02x %02x \n", param->value.str, | |||
| dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5]);fflush(stdout); | |||
| break; | |||
| } | |||
| } | |||
| try { | |||
| Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver ( | |||
| new Jack::JackAVBDriver("system", "avb_mc", engine, table, sid, dmac, eth_dev, | |||
| sample_rate, period_size, num_periods, adjust, capture_ports, playback_ports)); | |||
| if (driver->Open(period_size, sample_rate, 1, 1, capture_ports, playback_ports, | |||
| 0, "from_master", "to_master", 0, 0) == 0) { | |||
| return driver; | |||
| } else { | |||
| delete driver; | |||
| return NULL; | |||
| } | |||
| } catch (...) { | |||
| return NULL; | |||
| } | |||
| } | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| } | |||
| @@ -0,0 +1,65 @@ | |||
| /* | |||
| Copyright (C) 2016-2019 Christoph Kuhr | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (at your option) any later version. | |||
| This program 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 General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #ifndef __JackNetDriver__ | |||
| #define __JackNetDriver__ | |||
| #include "JackTimedDriver.h" | |||
| namespace Jack | |||
| { | |||
| /** | |||
| \Brief This class describes the Net Backend | |||
| */ | |||
| class JackAVBDriver : public JackWaiterDriver | |||
| { | |||
| private: | |||
| avb_driver_state_t avb_ctx; | |||
| int num_packets_even_odd; | |||
| public: | |||
| JackAVBDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, | |||
| char* stream_id, char* destination_mac, char* eth_dev, | |||
| int sample_rate, int period_size, int num_periods, int adjust, int capture_ports, int playback_ports); | |||
| virtual ~JackAVBDriver(); | |||
| int Close(); | |||
| int Attach(){return 0;} | |||
| int Detach(){return 0;} | |||
| int Read(); | |||
| int Write(); | |||
| bool Initialize(); | |||
| int AllocPorts(); | |||
| void FreePorts(); | |||
| // BufferSize can't be changed | |||
| bool IsFixedBufferSize(){return true;} | |||
| int SetBufferSize(jack_nframes_t buffer_size){return -1;} | |||
| int SetSampleRate(jack_nframes_t sample_rate){return -1;} | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -23,39 +23,11 @@ extern "C" | |||
| { | |||
| #endif | |||
| #include <stdio.h> | |||
| #include <stdbool.h> | |||
| #include <stdlib.h> | |||
| #include <stdint.h> | |||
| #include <string.h> | |||
| #include <malloc.h> | |||
| #include <sys/types.h> | |||
| #include <sys/errno.h> | |||
| #include <sys/fcntl.h> | |||
| #include <sys/mman.h> // Needed for mlockall() | |||
| #include <sys/time.h> // needed for getrusage | |||
| #include <sys/resource.h> // needed for getrusage | |||
| #include <unistd.h> // needed for sysconf(int name); | |||
| #include <errno.h> | |||
| #include <signal.h> | |||
| #include <time.h> | |||
| #include <malloc.h> | |||
| #include <sys/stat.h> | |||
| #include <sys/types.h> | |||
| #include <sys/errno.h> | |||
| #include <sched.h> | |||
| #include <pthread.h> | |||
| #include <sys/syscall.h> | |||
| #include <linux/sched.h> | |||
| #include <sys/mman.h> | |||
| #include "avb_definitions.h" | |||
| #include "media_clock_listener.h" | |||
| #include "mrp_client_control_socket.h" | |||
| #include "mrp_client_send_msg.h" | |||
| int init_avb_driver( avb_driver_state_t *avb_ctx, const char* name, | |||
| char* stream_id, char* destination_mac, | |||
| @@ -0,0 +1,43 @@ | |||
| /* | |||
| Copyright (C) 2016-2019 Christoph Kuhr | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (at your option) any later version. | |||
| This program 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 General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #ifndef JACK1722DRIVER_H | |||
| #define JACK1722DRIVER_H | |||
| #ifdef __cplusplus | |||
| extern "C" | |||
| { | |||
| #endif | |||
| #include <stdbool.h> | |||
| #include <sys/mman.h> // Needed for mlockall() | |||
| #include "avb_definitions.h" | |||
| #include "media_clock_listener.h" | |||
| int init_avb_driver( avb_driver_state_t *avb_ctx, const char* name, | |||
| char* stream_id, char* destination_mac, | |||
| int sample_rate, int period_size, int num_periods, int adjust, int capture_ports, int playback_ports); | |||
| int startup_avb_driver( avb_driver_state_t *avb_ctx); | |||
| uint64_t await_avtp_rx_ts( avb_driver_state_t *avb_ctx, int packet_num ); | |||
| int shutdown_avb_driver( avb_driver_state_t *avb_ctx); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif //JACK1722DRIVER_H | |||
| @@ -27,28 +27,14 @@ extern "C" | |||
| #define _GNU_SOURCE | |||
| #include <stdlib.h> | |||
| #include <stdint.h> | |||
| #include <unistd.h> | |||
| #include <pthread.h> | |||
| #include <poll.h> | |||
| #include <netinet/in.h> | |||
| #include <linux/if_packet.h> | |||
| #include <linux/if_ether.h> | |||
| #include <linux/if.h> | |||
| #include <linux/sockios.h> | |||
| #include <jack/types.h> | |||
| #include <jack/jack.h> | |||
| #include <jack/transport.h> | |||
| #include "jack/jslist.h" | |||
| #include "OpenAvnu/daemons/mrpd/mrpd.h" | |||
| #include "OpenAvnu/daemons/mrpd/mrp.h" | |||
| #include "OpenAvnu/daemons/mrpd/msrp.h" // spurious dep daemons/mrpd/msrp.h:50:#define MSRP_LISTENER_ASKFAILED | |||
| #define RETURN_VALUE_FAILURE 0 | |||
| #define RETURN_VALUE_SUCCESS 1 | |||
| @@ -0,0 +1,142 @@ | |||
| /* | |||
| Copyright (C) 2016-2019 Christoph Kuhr | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (at your option) any later version. | |||
| This program 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 General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #ifndef SRC_GLOBAL_DEFINITIONS_H_ | |||
| #define SRC_GLOBAL_DEFINITIONS_H_ | |||
| #ifdef __cplusplus | |||
| extern "C" | |||
| { | |||
| #endif | |||
| #define _GNU_SOURCE | |||
| #include <netinet/in.h> | |||
| #include <linux/if.h> | |||
| #include <jack/transport.h> | |||
| #include "jack/jslist.h" | |||
| //#include "OpenAvnu/daemons/mrpd/mrpd.h" | |||
| //#include "OpenAvnu/daemons/mrpd/mrp.h" | |||
| #define RETURN_VALUE_FAILURE 0 | |||
| #define RETURN_VALUE_SUCCESS 1 | |||
| #define MILISLEEP_TIME 1000000 | |||
| #define USLEEP_TIME 1000 | |||
| #define MAX_DEV_STR_LEN 32 | |||
| #define BUFLEN 1500 | |||
| #define ETHERNET_Q_HDR_LENGTH 18 | |||
| #define ETHERNET_HDR_LENGTH 14 | |||
| #define IP_HDR_LENGTH 20 | |||
| #define UDP_HDR_LENGTH 8 | |||
| #define AVB_ETHER_TYPE 0x22f0 | |||
| #define ARRAYSIZE(arr) (sizeof(arr) / sizeof(arr[0])) | |||
| typedef struct etherheader_q | |||
| { | |||
| unsigned char ether_dhost[6]; // destination eth addr | |||
| unsigned char ether_shost[6]; // source ether addr | |||
| unsigned int vlan_id; // VLAN ID field | |||
| unsigned short int ether_type; // packet type ID field | |||
| } etherheader_q_t; | |||
| typedef struct etherheader | |||
| { | |||
| unsigned char ether_dhost[6]; // destination eth addr | |||
| unsigned char ether_shost[6]; // source ether addr | |||
| unsigned short int ether_type; // packet type ID field | |||
| } etherheader_t; | |||
| typedef struct mrp_ctx{ | |||
| volatile int mrp_status; | |||
| volatile int domain_a_valid; | |||
| volatile int domain_b_valid; | |||
| int domain_class_a_id; | |||
| int domain_class_a_priority; | |||
| u_int16_t domain_class_a_vid; | |||
| int domain_class_b_id; | |||
| int domain_class_b_priority; | |||
| u_int16_t domain_class_b_vid; | |||
| }mrp_ctx_t; | |||
| typedef enum mrpStatus{ | |||
| TL_UNDEFINED, | |||
| TALKER_IDLE, | |||
| TALKER_ADVERTISE, | |||
| TALKER_ASKFAILED, | |||
| TALKER_READYFAILED, | |||
| TALKER_CONNECTING, | |||
| TALKER_CONNECTED, | |||
| TALKER_ERROR, | |||
| LISTENER_IDLE, | |||
| LISTENER_WAITING, | |||
| LISTENER_READY, | |||
| LISTENER_CONNECTED, | |||
| LISTENER_ERROR, | |||
| LISTENER_FAILED | |||
| } mrpStatus_t; | |||
| typedef struct _avb_driver_state avb_driver_state_t; | |||
| struct _avb_driver_state { | |||
| uint8_t streamid8[8]; | |||
| uint8_t destination_mac_address[6]; | |||
| unsigned char serverMACAddress[6]; | |||
| char avbdev[MAX_DEV_STR_LEN]; | |||
| struct sockaddr_in si_other_avb; | |||
| int raw_transport_socket; | |||
| struct ifreq if_idx; | |||
| struct ifreq if_mac; | |||
| pthread_t thread; | |||
| pthread_mutex_t threadLock; | |||
| pthread_cond_t dataReady; | |||
| jack_nframes_t sample_rate; | |||
| jack_nframes_t period_size; | |||
| jack_time_t period_usecs; | |||
| int num_packets; | |||
| int adjust; | |||
| unsigned int capture_channels; | |||
| unsigned int playback_channels; | |||
| JSList *capture_ports; | |||
| JSList *playback_ports; | |||
| JSList *playback_srcs; | |||
| JSList *capture_srcs; | |||
| jack_client_t *client; | |||
| }; | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* SRC_GLOBAL_DEFINITIONS_H_ */ | |||
| @@ -17,6 +17,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #include "avb_sockets.h" | |||
| #define DUMMY_STREAMID (0xABCDEF) | |||
| /* IEEE 1722 AVTP Receive Socket */ | |||
| @@ -0,0 +1,150 @@ | |||
| /* | |||
| Copyright (C) 2016-2019 Christoph Kuhr | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (at your option) any later version. | |||
| This program 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 General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #include "avb_sockets.h" | |||
| #define DUMMY_STREAMID (0xABCDEF) | |||
| /* IEEE 1722 AVTP Receive Socket */ | |||
| int enable_1722avtp_filter( FILE* filepointer, int raw_transport_socket, unsigned char *destinationMacAddress) | |||
| { | |||
| /* | |||
| tcpdump -i enp9s0 "ether dst 91:e0:f0:00:c3:51" -dd | |||
| { 0x20, 0, 0, 0x00000002 }, | |||
| { 0x15, 0, 3, 0xf000c351 }, | |||
| { 0x28, 0, 0, 0x00000000 }, | |||
| { 0x15, 0, 1, 0x000091e0 }, | |||
| { 0x6, 0, 0, 0x00040000 }, | |||
| { 0x6, 0, 0, 0x00000000 }, | |||
| */ | |||
| unsigned int low_mac=0, hi_mac=0; | |||
| low_mac = (((destinationMacAddress[0] & 0xFF) & 0xFFFFFFFF) << 8 ) | (destinationMacAddress[1] & 0xFF ); | |||
| hi_mac = (((destinationMacAddress[2] & 0xFF) & 0xFFFFFFFF) << 24 ) | (((destinationMacAddress[3] & 0xFF ) & 0xFFFFFFFF) << 16 ) | (((destinationMacAddress[4] & 0xFF ) & 0xFFFFFFFF) << 8 ) | (destinationMacAddress[5] & 0xFF ); | |||
| struct sock_filter code[] = { | |||
| { 0x20, 0, 0, 0x00000002 }, | |||
| { 0x15, 0, 3, hi_mac }, | |||
| { 0x28, 0, 0, 0x00000000 }, | |||
| { 0x15, 0, 1, low_mac }, | |||
| { 0x6, 0, 0, 0x00040000 }, | |||
| { 0x6, 0, 0, 0x00000000 }, | |||
| }; | |||
| struct sock_fprog bpf = { | |||
| .len = ARRAYSIZE(code), | |||
| .filter = code, | |||
| }; | |||
| if(setsockopt(raw_transport_socket, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf)) < 0) { | |||
| fprintf(filepointer, "setsockopt error: %s \n", strerror(errno));fflush(filepointer); | |||
| return RETURN_VALUE_FAILURE; | |||
| } | |||
| return RETURN_VALUE_FAILURE; | |||
| } | |||
| int create_RAW_AVB_Transport_Socket( FILE* filepointer, int* raw_transport_socket, const char* eth_dev) | |||
| { | |||
| struct ifreq ifr; | |||
| memset((char*)&ifr, 0, sizeof(struct ifreq)); | |||
| int sockopt=0; | |||
| struct ifreq ifopts; | |||
| memset((char*)&ifopts, 0, sizeof(struct ifreq)); | |||
| int s; | |||
| strncpy (ifr.ifr_name, eth_dev, IFNAMSIZ - 1); | |||
| ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0'; | |||
| if (( s = socket(PF_PACKET, SOCK_RAW, htons(AVB_ETHER_TYPE/*ETH_P_ALL*/))) < 0){ | |||
| fprintf(filepointer, "[RAW_TRANSPORT] Error creating RAW Socket \n");fflush(filepointer); | |||
| return RETURN_VALUE_FAILURE; | |||
| } | |||
| *raw_transport_socket = s; | |||
| strncpy(ifopts.ifr_name, ifr.ifr_name, IFNAMSIZ-1); | |||
| if( ioctl(*raw_transport_socket, SIOCGIFFLAGS, &ifopts) == -1) { | |||
| fprintf(filepointer, "[RAW_TRANSPORT] No such interface");fflush(filepointer); | |||
| fprintf(filepointer, "Zero \n");fflush(filepointer); | |||
| close(*raw_transport_socket); | |||
| return RETURN_VALUE_FAILURE; | |||
| } | |||
| ifopts.ifr_flags |= IFF_PROMISC; | |||
| if( ioctl(*raw_transport_socket, SIOCSIFFLAGS, &ifopts) == -1){ | |||
| fprintf(filepointer, "[RAW_TRANSPORT] Interface is down. \n");fflush(filepointer); | |||
| close(*raw_transport_socket); | |||
| return RETURN_VALUE_FAILURE; | |||
| } | |||
| if (setsockopt(*raw_transport_socket, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof( sockopt)) == -1) { | |||
| fprintf(filepointer, "[RAW_TRANSPORT] setsockopt failed \n");fflush(filepointer); | |||
| close(*raw_transport_socket); | |||
| return RETURN_VALUE_FAILURE; | |||
| } | |||
| /* Set Timestamping Option => requires recvmsg to be used => timestamp in ancillary data */ | |||
| int timestamp_flags = 0; | |||
| // timestamp_flags |= SOF_TIMESTAMPING_TX_HARDWARE; | |||
| timestamp_flags |= SOF_TIMESTAMPING_RX_HARDWARE; | |||
| timestamp_flags |= SOF_TIMESTAMPING_SYS_HARDWARE; | |||
| timestamp_flags |= SOF_TIMESTAMPING_RAW_HARDWARE; | |||
| struct hwtstamp_config hwconfig; | |||
| memset( &hwconfig, 0, sizeof( hwconfig )); | |||
| hwconfig.rx_filter = HWTSTAMP_FILTER_ALL; | |||
| // hwconfig.tx_type = HWTSTAMP_TX_OFF; | |||
| hwconfig.tx_type = HWTSTAMP_TX_ON; /* NECESARRY FOR CMSGs TO WORK*/ | |||
| struct ifreq hwtstamp; | |||
| memset((char*)&hwtstamp, 0, sizeof(struct ifreq)); | |||
| strncpy(hwtstamp.ifr_name, ifr.ifr_name, IFNAMSIZ-1); | |||
| hwtstamp.ifr_data = (void *) &hwconfig; | |||
| if( ioctl( *raw_transport_socket, SIOCSHWTSTAMP, &hwtstamp ) == -1 ) { | |||
| fprintf(filepointer, "[RAW TRANSPORT] ioctl timestamping failed %d %s \n", errno, strerror(errno));fflush(filepointer); | |||
| close(*raw_transport_socket); | |||
| return RETURN_VALUE_FAILURE; | |||
| } | |||
| if (setsockopt(*raw_transport_socket, SOL_SOCKET, SO_TIMESTAMPING, ×tamp_flags, sizeof(timestamp_flags) ) == -1) { | |||
| fprintf(filepointer, "[RAW TRANSPORT] setsockopt timestamping failed %d %s \n", errno, strerror(errno));fflush(filepointer); | |||
| close(*raw_transport_socket); | |||
| return RETURN_VALUE_FAILURE; | |||
| } else { | |||
| fprintf(filepointer, "[RAW TRANSPORT] Timestamp Socket \n");fflush(filepointer); | |||
| } | |||
| if (setsockopt(*raw_transport_socket, SOL_SOCKET, SO_BINDTODEVICE, eth_dev, IFNAMSIZ-1) == -1) { | |||
| fprintf(filepointer, "[RAW_TRANSPORT] SO_BINDTODEVICE failed \n");fflush(filepointer); | |||
| close(*raw_transport_socket); | |||
| return RETURN_VALUE_FAILURE; | |||
| } | |||
| return RETURN_VALUE_SUCCESS; | |||
| } | |||
| @@ -26,38 +26,15 @@ extern "C" | |||
| #endif | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <unistd.h> | |||
| #include <string.h> | |||
| #include <stdint.h> | |||
| #include <unistd.h> | |||
| #include <signal.h> | |||
| #include <errno.h> | |||
| #include <sys/types.h> | |||
| #include <sys/socket.h> | |||
| #include <sys/ioctl.h> | |||
| #include <fcntl.h> | |||
| #include <arpa/inet.h> | |||
| #include <netinet/ether.h> | |||
| #include <netinet/in.h> | |||
| #include <netinet/udp.h> //Provides declarations for udp header | |||
| #include <netinet/ip.h> //Provides declarations for udp header | |||
| #include <netdb.h> | |||
| #include <ifaddrs.h> | |||
| #include <linux/if_packet.h> | |||
| #include <linux/if_ether.h> | |||
| #include <linux/net_tstamp.h> | |||
| #include <linux/if.h> | |||
| #include <linux/sockios.h> | |||
| //#include <linux/ip.h> | |||
| #include <linux/ptp_clock.h> | |||
| #include <linux/filter.h> | |||
| #include <poll.h> | |||
| #include <sched.h> | |||
| #include "avb_definitions.h" | |||
| @@ -0,0 +1,40 @@ | |||
| /* | |||
| Copyright (C) 2016-2019 Christoph Kuhr | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (at your option) any later version. | |||
| This program 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 General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #ifndef AVBSOCKET_H_ | |||
| #define AVBSOCKET_H_ | |||
| #ifdef __cplusplus | |||
| extern "C" | |||
| { | |||
| #endif | |||
| #include <stdio.h> | |||
| #include "avb_definitions.h" | |||
| int enable_1722avtp_filter( FILE* filepointer, int raw_transport_socket, unsigned char *destinationMacAddress); | |||
| int create_RAW_AVB_Transport_Socket( FILE* filepointer, int* raw_transport_socket, const char* eth_dev); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif | |||
| @@ -24,35 +24,10 @@ extern "C" | |||
| { | |||
| #endif | |||
| #include <unistd.h> | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include <stdint.h> | |||
| #include <inttypes.h> | |||
| #include <errno.h> | |||
| #include <signal.h> | |||
| #include <time.h> | |||
| #include <pthread.h> | |||
| #include <sched.h> | |||
| #include <linux/types.h> | |||
| #include <sys/syscall.h> | |||
| #include <linux/sched.h> | |||
| #include <sys/stat.h> | |||
| #include <sys/errno.h> | |||
| #include <sys/types.h> | |||
| #include <sys/ipc.h> | |||
| #include <mqueue.h> | |||
| #include <sys/msg.h> | |||
| #include <sys/stat.h> | |||
| #include <sys/wait.h> | |||
| #include <sys/resource.h> | |||
| #include "avb_definitions.h" | |||
| #include "avb_sockets.h" | |||
| #include "mrp_client_interface.h" | |||
| #include "mrp_client_control_socket.h" | |||
| int avtp_mcl_create( FILE* filepointer, avb_driver_state_t **avb_ctx, const char* avb_dev_name, | |||
| char* stream_id, char* destination_mac, | |||
| @@ -0,0 +1,42 @@ | |||
| /* | |||
| Copyright (C) 2016-2019 Christoph Kuhr | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (at your option) any later version. | |||
| This program 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 General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #ifndef MEDIACLOCKLISTENER_H | |||
| #define MEDIACLOCKLISTENER_H | |||
| #ifdef __cplusplus | |||
| extern "C" | |||
| { | |||
| #endif | |||
| #include <mqueue.h> | |||
| #include "avb_sockets.h" | |||
| #include "mrp_client_interface.h" | |||
| int avtp_mcl_create( FILE* filepointer, avb_driver_state_t **avb_ctx, const char* avb_dev_name, | |||
| char* stream_id, char* destination_mac, | |||
| struct sockaddr_in **si_other_avb, struct pollfd **avtp_transport_socket_fds); | |||
| void avtp_mcl_delete( FILE* filepointer, avb_driver_state_t **avb_ctx); | |||
| uint64_t avtp_mcl_wait_for_rx_ts( FILE* filepointer, avb_driver_state_t **avb_ctx, | |||
| struct sockaddr_in **si_other_avb, struct pollfd **avtp_transport_socket_fds, int packet_num ); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif //MEDIACLOCKLISTENER_H | |||
| @@ -23,21 +23,6 @@ extern "C" | |||
| { | |||
| #endif | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <stdint.h> | |||
| #include <string.h> | |||
| #include <unistd.h> // needed for sysconf(int name); | |||
| #include <errno.h> | |||
| #include <signal.h> | |||
| #include <time.h> | |||
| #include <malloc.h> | |||
| #include <sys/stat.h> | |||
| #include <sys/types.h> | |||
| #include <sys/errno.h> | |||
| #include <arpa/inet.h> | |||
| #include "avb_definitions.h" | |||
| #include "mrp_client_send_msg.h" | |||
| @@ -0,0 +1,38 @@ | |||
| /* | |||
| Copyright (C) 2016-2019 Christoph Kuhr | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (at your option) any later version. | |||
| This program 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 General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #ifndef _MRP_CONTROL_SOCKET_H_ | |||
| #define _MRP_CONTROL_SOCKET_H_ | |||
| #ifdef __cplusplus | |||
| extern "C" | |||
| { | |||
| #endif | |||
| //#include <arpa/inet.h> | |||
| #include "avb_definitions.h" | |||
| #include "mrp_client_send_msg.h" | |||
| int mrp_client_get_Control_socket( ); | |||
| int mrp_client_init_Control_socket( FILE* filepointer ); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* _MRP_CONTROL_SOCKET_H_ */ | |||
| @@ -23,22 +23,8 @@ extern "C" | |||
| { | |||
| #endif | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <stdint.h> | |||
| #include <string.h> | |||
| #include <unistd.h> // needed for sysconf(int name); | |||
| #include <errno.h> | |||
| #include <signal.h> | |||
| #include <time.h> | |||
| #include <malloc.h> | |||
| #include <sys/stat.h> | |||
| #include <sys/types.h> | |||
| #include <sys/errno.h> | |||
| #include "avb_definitions.h" | |||
| #include "mrp_client_control_socket.h" | |||
| #include "mrp_client_send_msg.h" | |||
| int mrp_client_getDomain_joinVLAN(FILE* filepointer, avb_driver_state_t **avb_ctx, mrp_ctx_t *mrp_ctx); | |||
| @@ -0,0 +1,42 @@ | |||
| /* | |||
| Copyright (C) 2016-2019 Christoph Kuhr | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (at your option) any later version. | |||
| This program 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 General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #ifndef _MRP_CL_IF_H_ | |||
| #define _MRP_CL_IF_H_ | |||
| #ifdef __cplusplus | |||
| extern "C" | |||
| { | |||
| #endif | |||
| #include "avb_definitions.h" | |||
| #include "mrp_client_control_socket.h" | |||
| #include "OpenAvnu/daemons/mrpd/mrpd.h" | |||
| #include "OpenAvnu/daemons/mrpd/mrp.h" | |||
| int mrp_client_getDomain_joinVLAN(FILE* filepointer, avb_driver_state_t **avb_ctx, mrp_ctx_t *mrp_ctx); | |||
| int mrp_client_listener_await_talker(FILE* filepointer,avb_driver_state_t **avb_ctx, mrp_ctx_t *mrp_ctx); | |||
| int mrp_client_listener_send_ready(FILE* filepointer,avb_driver_state_t **avb_ctx, mrp_ctx_t *mrp_ctx); | |||
| int mrp_client_listener_send_leave(FILE* filepointer,avb_driver_state_t **avb_ctx, mrp_ctx_t *mrp_ctx); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* _MRP_CL_IF_H_ */ | |||
| @@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include "mrp_client_send_msg.h" | |||
| int mrp_client_send_mrp_msg(FILE* filepointer, int control_socket, char *notify_data, int notify_len) | |||
| { | |||
| struct sockaddr_in addr; | |||
| @@ -0,0 +1,40 @@ | |||
| /* | |||
| Copyright (C) 2016-2019 Christoph Kuhr | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (at your option) any later version. | |||
| This program 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 General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #include "mrp_client_send_msg.h" | |||
| #include "OpenAvnu/daemons/mrpd/mrpd.h" | |||
| #include "OpenAvnu/daemons/mrpd/mrp.h" | |||
| int mrp_client_send_mrp_msg(FILE* filepointer, int control_socket, char *notify_data, int notify_len) | |||
| { | |||
| struct sockaddr_in addr; | |||
| if ( control_socket == -1 ) | |||
| return RETURN_VALUE_FAILURE; | |||
| if (notify_data == NULL) | |||
| return RETURN_VALUE_FAILURE; | |||
| memset(&addr, 0, sizeof(addr)); | |||
| addr.sin_family = AF_INET; | |||
| addr.sin_port = htons(MRPD_PORT_DEFAULT); | |||
| addr.sin_addr.s_addr = inet_addr("127.0.0.1"); | |||
| inet_aton("127.0.0.1", &addr.sin_addr); | |||
| return sendto( control_socket, notify_data, notify_len, 0, (struct sockaddr*)&addr, (socklen_t)sizeof(addr)); | |||
| } | |||
| @@ -24,19 +24,9 @@ extern "C" | |||
| { | |||
| #endif | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <stdint.h> | |||
| #include <string.h> | |||
| #include <unistd.h> // needed for sysconf(int name); | |||
| #include <errno.h> | |||
| #include <signal.h> | |||
| #include <time.h> | |||
| #include <malloc.h> | |||
| #include <sys/stat.h> | |||
| #include <sys/types.h> | |||
| #include <sys/errno.h> | |||
| #include "avb_definitions.h" | |||
| @@ -0,0 +1,43 @@ | |||
| /* | |||
| Copyright (C) 2016-2019 Christoph Kuhr | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (at your option) any later version. | |||
| This program 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 General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #ifndef _MRP_SEND_MSG_H_ | |||
| #define _MRP_SEND_MSG_H_ | |||
| #ifdef __cplusplus | |||
| extern "C" | |||
| { | |||
| #endif | |||
| #include <string.h> | |||
| #include <errno.h> | |||
| #include <malloc.h> | |||
| //#include <sys/stat.h> | |||
| //#include <sys/types.h> | |||
| //#include <sys/errno.h> | |||
| #include "avb_definitions.h" | |||
| int mrp_client_send_mrp_msg(FILE* filepointer, int control_socket, char *notify_data, int notify_len); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* _MRP_SEND_MSG_H_ */ | |||