From 6d88c555019f32509f303e23dcfbba824fecd2ee Mon Sep 17 00:00:00 2001 From: Chris Hiszpanski Date: Thu, 18 Apr 2019 00:55:30 -0700 Subject: Initial public commit. mDNS and SDP are functional. Otherwise, library is still very much a work in progress. All tests pass. --- include/config.h | 46 +++++++++++++++++ include/ice.h | 129 +++++++++++++++++++++++++++++++++++++++++++++++ include/peerconn.h | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/runloop.h | 111 +++++++++++++++++++++++++++++++++++++++++ include/str.h | 34 +++++++++++++ include/stun.h | 134 +++++++++++++++++++++++++++++++++++++++++++++++++ include/urtc.h | 34 +++++++++++++ include/urtc/opts.h | 22 +++++++++ 8 files changed, 650 insertions(+) create mode 100644 include/config.h create mode 100644 include/ice.h create mode 100644 include/peerconn.h create mode 100644 include/runloop.h create mode 100644 include/str.h create mode 100644 include/stun.h create mode 100644 include/urtc.h create mode 100644 include/urtc/opts.h (limited to 'include') diff --git a/include/config.h b/include/config.h new file mode 100644 index 0000000..a003218 --- /dev/null +++ b/include/config.h @@ -0,0 +1,46 @@ +/* + * liburtc + * Copyright (C) 2019 Chris Hiszpanski + * + * 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 3 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, see . + */ + +#ifndef URTC_CONFIG_H +#define URTC_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ice.h" + +/* Peer connection configuration */ +typedef struct urtc_config { + urtc_ice_server_t ice_servers[ICE_MAX_SERVERS]; + + // TODO video_source_t *vsrc; + // TODO video_sink_t *vsnk; + + // TODO audio_source_t *asrc; + // TODO audio_sink_t *asnk; + + // TODO data_source_t *dsrc; + // TODO data_sink_t *dsnk; +} urtc_config_t; + +#ifdef __cplusplus +} +#endif + +#endif /* URTC_CONFIG_H */ diff --git a/include/ice.h b/include/ice.h new file mode 100644 index 0000000..8b7251f --- /dev/null +++ b/include/ice.h @@ -0,0 +1,129 @@ +/* + * liburtc + * Copyright (C) 2019 Chris Hiszpanski + * + * 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 3 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, see . + */ + +#ifndef URTC_ICE_H +#define URTC_ICE_H + +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Maximum number of ICE bases. Each network interface address is a base. */ +#define ICE_MAX_BASES 16 + +/* Maximum number of supported ICE (i.e. STUN or TURN) servers */ +#define ICE_MAX_SERVERS 16 + + +///////////////////////////// TYPE DEFINITIONS ///////////////////////////// + +// STUN or TURN server +typedef struct { + char *url; + char *username; /* ignored for stun urls */ + char *credential; /* ignored for stun urls */ +} urtc_ice_server_t; + +// ICE base +typedef struct { +} ice_base_t; + +// ICE component +typedef enum { + ICE_COMPONENT_NULL = 0, + ICE_COMPONENT_RTP, + ICE_COMPONENT_RTCP +} ice_component_t; + +// ICE candidate +typedef struct { + ice_component_t component; + uint16_t port; + uint32_t priority; +} ice_candidate_t; + +typedef struct { + ice_candidate_t local; + ice_candidate_t remote; +} ice_candidate_pair_t; + +// See https://tools.ietf.org/html/rfc8445#section-6.1.2.1 +typedef enum { + CHECKLIST_STATE_RUNNING = 0, + CHECKLIST_STATE_COMPLETED, + CHECKLIST_STATE_FAILED +} ice_checklist_state_t; + +typedef struct { + ice_checklist_state_t state; +} ice_checklist_t; + +// ICE agent object +typedef struct { + pthread_t thread; + ice_checklist_t checklist; + ice_base_t bases[ICE_MAX_BASES]; + + int nfds; + fd_set readfds; + fd_set writefds; + fd_set errorfds; + + struct timeval ta; + + bool cancelled; +} ice_agent_t; + + +/////////////////////////// FORWARD DECLARATIONS /////////////////////////// + +/** + * Create new ICE agent + * + * Each agent creates a separate thread for processing network i/o events. + * + * \param agent[out] Pointer to agent object pointer + * + * \return 0 on success. Negative on error. + */ +int ice_agent_create(ice_agent_t **agent); + +/** + * Destroy ICE agent + * + * Stops agent thread (if running) and frees memory. + * + * \param agent[in] Pointer to agent object + * + * \return 0 on success. Negative on error. + */ +int ice_agent_destroy(ice_agent_t *agent); + +int ice_gather_host_candidates(); + +#ifdef __cplusplus +} +#endif + +#endif /* URTC_ICE_H */ diff --git a/include/peerconn.h b/include/peerconn.h new file mode 100644 index 0000000..feecc0e --- /dev/null +++ b/include/peerconn.h @@ -0,0 +1,140 @@ +/* + * liburtc + * Copyright (C) 2019 Chris Hiszpanski + * + * 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 3 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, see . + */ + +#ifndef URTC_PEERCONN_H +#define URTC_PEERCONN_H + +#include "config.h" +#include "ice.h" +#include "sdp.h" +#include "runloop.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**************************** TYPE DEFINITIONS ****************************/ + +// Event callback function type. Takes and returns void pointers. +typedef void *(*event_callback_t)(void *arg); + +// Peer connection +typedef struct urtc_peerconn { + uint8_t n; + + // Interactive connectivity establishment agent + ice_agent_t *agent; + + // Local and remote session descriptions + urtc_sdp_t *ldesc; + urtc_sdp_t *rdesc; + + // Event callbacks + void (*onIceCandidate)(const char *cand, void *arg); + void (*onIceGatheringStateChange)(int state); + void (*onIceConnectionStateChange)(int state); + void (*onSignalingStateChange)(int state); + void (*onTrack)(int track); + + // Run loop for event handling + runloop_t runloop; +} urtc_peerconn_t; + + +/************************** FORWARD DECLARATIONS **************************/ + +/** + * Create a new peer connection. + * + * \param pc[out] New peer connection. + * \param cfg[in] Peer connection configuration. + * + * \return 0 on success. Negative on error. + */ +int urtc_peerconn_create(urtc_peerconn_t **pc, const urtc_config_t *cfg); + +/** + * Adds received ICE candidate to ICE agent. + * + * If `cand` is a NULL pointer or empty string, it signals that all remote + * candidates have been delivered (i.e. end-of-candidates). + * + * \param pc[in] Peer connection. + * \param cand[in] ICE candidate. + * + * \return 0 on success. Negative on error. + */ +int urtc_peerconn_add_ice_candidate(urtc_peerconn_t *pc, const char *cand); + +/** + * Set remote description. + * + * \param pc[in] Peer connection. + * \param desc[in] Session description protocol string. + * + * \return 0 on success. Negative on error. + */ +int urtc_peerconn_set_remote_description(urtc_peerconn_t *pc, const char *desc); + +/** + * Set local description. + * + * \param pc[in] Peer connection. + * \param desc[in] Session description protocol string. + * + * \return 0 on success. Negative on error. + */ +int urtc_peerconn_set_local_description(urtc_peerconn_t *pc, const char *desc); + +/** + * Create offer. + * + * \param pc[in] Peer connection. + * \param offer[out] Session description to send to remote peer. Caller must + * free. + * + * \return 0 on success. Negative on error. + */ +int urtc_peerconn_create_offer(urtc_peerconn_t *pc, char **offer); + +/** + * Create answer. + * + * \param pc[in] Peer connection + * \param answer[out] Session description to send to remote peer. Caller must + * free. + * + * \return 0 on success. Negative on error. + */ +int urtc_peerconn_create_answer(urtc_peerconn_t *pc, char **answer); + +/** + * Teardown a peer connection. + * + * \param pc[in] Peer connection. + * + * \return 0 on success. Negative on error. + */ +int urtc_peerconn_destroy(urtc_peerconn_t *pc); + +#ifdef __cplusplus +} +#endif + +#endif /* URTC_PEERCONN_H */ diff --git a/include/runloop.h b/include/runloop.h new file mode 100644 index 0000000..ea840e7 --- /dev/null +++ b/include/runloop.h @@ -0,0 +1,111 @@ +/* + * liburtc + * Copyright (C) 2019 Chris Hiszpanski + * + * 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 3 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, see . + */ + +/** + * @file runloop.h + * Event loop + * A more elaborate file description. + */ + +#ifndef URTC_RUNLOOP_H +#define URTC_RUNLOOP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +typedef void *(*callback_t)(int fd, void *arg); + +typedef struct { + // File descriptor sets for poll(). + struct pollfd *fds; + nfds_t nfds; + + // Callback array. Index into array is file descriptor. + callback_t *callbacks; + void **args; + + // Pipe for aborting blocked poll(). Allows dynamic adds/removes. + int abortpipe[2]; + bool done; + + // Run loop thread ID + pthread_t tid; +} runloop_t; + +/** + * Create a new run loop + * + * Each run loop creates a separate thread which then repeatedly poll()s + * for events. Upon receiving an event, the run loop calls the respective + * file descriptor's callback function. + * + * @param[out] rl Pointer to run loop struct + */ +int urtc__runloop_create(runloop_t *rl); + +/** + * Add file descriptor to run loop + * + * @param rl Run loop + * @param fd File descriptor + * @param events Events to monitor (see struct pollfd) + * @param cb Callback to run on activity + * @param arg User-specified argument to pass to callback + * + * @return Zero on success. Negative on error. + */ +int urtc__runloop_add( + runloop_t *rl, + int fd, + short events, + void *(*cb)(int fd, void *arg), + void *arg +); + +/** + * Remove a file descriptor from the run loop. No more events will be + * processed for this file descriptor. + * + * @param rl Run loop. + * @param fd File descriptor. + * + * @return Zero on success. Negative on error. + */ +int urtc__runloop_remove(runloop_t *rl, int fd); + +int urtc__runloop_join(runloop_t *rl); + +/** + * Destroy a run loop + * + * @param rl Pointer to run loop object + * + * @return Zero on success; negative on error. On error, errno is set. + */ +int urtc__runloop_destroy(runloop_t *rl); + +#ifdef __cplusplus +} +#endif + +#endif /* URTC_RUNLOOP_H */ diff --git a/include/str.h b/include/str.h new file mode 100644 index 0000000..f0164d3 --- /dev/null +++ b/include/str.h @@ -0,0 +1,34 @@ +/* + * liburtc + * Copyright (C) 2019 Chris Hiszpanski + * + * 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 3 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, see . + */ + +#ifndef URTC_STR_H +#define URTC_STR_H + +#include + +typedef struct { + char *string; + size_t length; + size_t capacity; +} str_t; + +str_t str_create_empty(size_t capacity); +str_t str_append(const str_t str, const char *c_str); +void str_destroy(str_t s); + +#endif diff --git a/include/stun.h b/include/stun.h new file mode 100644 index 0000000..126e7f5 --- /dev/null +++ b/include/stun.h @@ -0,0 +1,134 @@ +/* + * liburtc + * Copyright (C) 2019 Chris Hiszpanski + * + * 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 3 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, see . + */ + +#ifndef URTC_STUN_H +#define URTC_STUN_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define SIZEOF_STUN_HDR 20 + +// STUN Classes +#define STUN_CLASS_REQUEST 0 +#define STUN_CLASS_INDICTATION 1 +#define STUN_CLASS_SUCCESS 2 +#define STUN_CLASS_ERROR 3 + +// STUN Methods +#define STUN_METHOD_RESERVED 0 +#define STUN_METHOD_BINDING 1 + + +///////////////////////////// TYPE DEFINITIONS ///////////////////////////// + +typedef struct { + int rc; // Retransmission count + int rto; // Retransmission timeout (in ms) + int sockfd; // Socket file descriptor +} stun_client_t; + +typedef struct { + char *server; +} stun_client_config_t; + +// STUN Message Header +typedef struct __attribute__((__packed__)) { + uint16_t reserved:2; // Upper two bits are 0 + uint16_t type:14; // 14-bit type + uint16_t msglen; // Message length + uint32_t cookie; // Magic cookie + uint8_t txid[12]; // Transaction ID +} stun_msg_hdr_t; + +// STUN Attribute +typedef struct { + uint16_t type; // Attribute type + uint16_t len; // Value length, prior to padding + uint8_t *val; // Pointer to attribute value +} stun_attr_t; + +// STUN Attribute: MAPPED-ADDRESS +typedef struct __attribute__((__packed__)) { + uint8_t reserved; + uint8_t family; + uint16_t port; + union { + uint8_t ipv4[4]; // IPv4 address is 32-bits + uint8_t ipv6[16]; // IPv6 address is 128-bits + }; +} stun_attr_mapped_address_t; + +// STUN Attribute: XOR-MAPPED-ADDRESS +typedef stun_attr_mapped_address_t stun_attr_xor_mapped_address_t; + +// STUN Attribute: USERNAME + + +////////////////////////////////// MACROS ////////////////////////////////// + +// Get class from message header type +#define CLASS(typ) (((typ >> 7) & 0x2) | ((typ >> 4) & 0x1)) + +// Get method from message header type +#define METHOD(typ) (((typ >> 2) & 0xF80) | ((typ >> 1) & 0x70) | (typ & 0xF)) + +#define TYPE(cls, mthd) ( \ + ((mthd & 0xF80) << 2) | \ + ((cls & 0x2) << 7) | \ + ((mthd & 0x70) << 1) | \ + ((cls & 0x1) << 4) | \ + (mthd & 0xF) \ +) + + +/////////////////////////// FORWARD DECLARATIONS /////////////////////////// + +/** + * (callback) Binding request response handler + * + * @param[in] name + * @param[in] arg User argument + */ +typedef void (*stun_client_binding_response_callback)( + const char *name, + void *arg +); + +/** + * Sends a STUN binding request to the specified server + * + * @param[in] srv Server (hostname or IP address) + * @param[in] cb Handler to call when a response is received + * @param[in] arg Optional user argument to pass to callback + */ +err_t stun_client_binding_request( + runloop_t *rl, + const char *srv, + stun_client_binding_response_callback cb, + void *arg +); + +#ifdef __cplusplus +} +#endif + +#endif /* URTC_STUN_H */ diff --git a/include/urtc.h b/include/urtc.h new file mode 100644 index 0000000..3eabba0 --- /dev/null +++ b/include/urtc.h @@ -0,0 +1,34 @@ +/* + * liburtc + * Copyright (C) 2019 Chris Hiszpanski + * + * 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 3 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, see . + */ + +#ifndef URTC_H +#define URTC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "config.h" +#include "err.h" +#include "peerconn.h" + +#ifdef __cplusplus +} +#endif + +#endif /* URTC_H */ diff --git a/include/urtc/opts.h b/include/urtc/opts.h new file mode 100644 index 0000000..7e5200b --- /dev/null +++ b/include/urtc/opts.h @@ -0,0 +1,22 @@ +/* + * liburtc + * Copyright (C) 2019 Chris Hiszpanski + * + * 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 3 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, see . + */ + +#ifndef URTC_OPTS_H +#define URTC_OPTS_H + +#endif /* URTC_OPTS_H */ -- cgit v1.2.3