Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐧 added unix_udp_socket.cpp for linux #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ project( VoIP_Project )
set( BUILD_TESTING OFF CACHE BOOL "Build tests (includes tests in all subprojects)." )
set( VOIP_BUILD_OPUS ON CACHE BOOL "Build opus audio coding library." )

link_libraries(m)

include(CheckCXXCompilerFlag)

CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
Expand All @@ -27,7 +29,7 @@ endif()
if( ${CMAKE_SYSTEM_NAME} STREQUAL Windows )
set( AUDIO_WINDOWS_WASAPI ON CACHE BOOL "Set WASAPI audio driver for Windows." )
elseif( ${CMAKE_SYSTEM_NAME} STREQUAL Linux )
set( AUDIO_LINUX_ALSA ON CACHE BOOL "Set ALSA audio driver for Linux." )
set( AUDIO_LINUX_PULSE ON CACHE BOOL "Set ALSA audio driver for Linux." )
elseif( ${CMAKE_SYSTEM_NAME} STREQUAL Darwin )
set( AUDIO_OSX_CORE ON CACHE BOOL "Set CoreAudio audio driver for OSX." )
else()
Expand Down
6 changes: 3 additions & 3 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ set( SRC main.cpp
# Windows only
set( WIN_SRC windows_udp_socket.cpp )
# TODO Linux / OSX only
# set( UNIX_SRC unix_udp_socket.cpp )
set( UNIX_SRC unix_udp_socket.cpp )

set( HDR voip_project.h
audio_buffer.h
Expand All @@ -35,8 +35,8 @@ set( HDR voip_project.h

if( ${CMAKE_SYSTEM_NAME} STREQUAL Windows )
list( APPEND SRC ${WIN_SRC} )
#else()
# list( APPEND SRC ${UNIX_SRC} )
else()
list( APPEND SRC ${UNIX_SRC} )
endif()

set( EXECUTABLE_NAME voip_project)
Expand Down
1 change: 1 addition & 0 deletions src/audio_mixer.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#define VOIP_AUDIO_MIXER_H_

#include <cstdint>
#include <cstdlib>

class AudioMixer
{
Expand Down
1 change: 1 addition & 0 deletions src/playout_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#define VOIP_PLAYOUT_BUFFER_H_

#include "audio_buffer.h"
#include <cstring>

class PlayoutBuffer {
public:
Expand Down
2 changes: 2 additions & 0 deletions src/receiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#ifndef VOIP_RECEIVER_H
#define VOIP_RECEIVER_H

#include <algorithm>
#include <cstring>
#include <string>
#include <thread>
#include <iostream>
Expand Down
1 change: 1 addition & 0 deletions src/soundcard_interaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "RtAudio.h"

#include "audio_buffer.h"
#include <cstring>

// TODO after AudioBuffer is coded
class SoundcardAudioProcessor {
Expand Down
10 changes: 10 additions & 0 deletions src/udp_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,18 @@
#define _WINSOCK_DEPRECATED_NO_WARNINGS 1
#define NOMINMAX 1

#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else

#include <sys/socket.h>
#include <sys/types.h>

#define SOCKET int

#endif


class SimpleWindowsUpdSocket
{
Expand Down
234 changes: 234 additions & 0 deletions src/unix_udp_socket.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@

#include "udp_socket.h"

#include <netdb.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <cstring>
static const int INVALID_SOCKET = -1;
static const int SOCKET_ERROR = -1;

#define ioctlsocket ioctl

SimpleWindowsUpdSocket::SimpleWindowsUpdSocket() : connectSocket_(INVALID_SOCKET), addressInfo_(), isOpen_(false), isAddressSet_(false)
{
// connectSocket_ = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
// WSADATA wsaData;
// int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
// if (iResult != 0)
// {
// std::cerr << "WSAStartup failed: " << iResult << std::endl;
// }

}

/**
* Initializes addressInfo_ property with passed ipV4 address and port
*/
void SimpleWindowsUpdSocket::setAddress(std::string address, std::string port)
{
if (isOpen_) close();

port_ = port;
struct addrinfo hints;


memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;

int iResult = getaddrinfo(address.c_str(), port.c_str(), &hints, &addressInfo_);
if (iResult != 0)
{
std::cerr << "getaddrinfo failed failed: " << iResult << std::endl;
}
else
{
if (addressInfo_->ai_canonname)
std::cerr << "Canonical name of socket: " << addressInfo_->ai_canonname << std::endl;

if (addressInfo_->ai_family != AF_INET)
{
addressInfo_ = nullptr;
isAddressSet_ = true;
std::cerr << "SocketAddress::setAddress(): Socket addresses other than ipv4 not supported!" << std::endl;
}
}
isAddressSet_ = true;
}

/**
* Initializes connectSocket_ with address information form addressInfo_
*/
void SimpleWindowsUpdSocket::open()
{
if (isAddressSet_ == false) return;

connectSocket_ = socket(addressInfo_->ai_family, addressInfo_->ai_socktype, addressInfo_->ai_protocol);

timeout_.tv_sec = 0;
timeout_.tv_usec = 100000;
// Set up the file descriptor set for timeout check


FD_ZERO(&socketArray_);
FD_SET(connectSocket_, &socketArray_);

if (connectSocket_ == INVALID_SOCKET)
{
std::cerr << "Error at socket(): " << strerror(errno) << std::endl;
freeaddrinfo(addressInfo_);
// WSACleanup();
}

isOpen_ = true;

int32_t reuseaddr = 1;
if (::setsockopt(connectSocket_, SOL_SOCKET, SO_REUSEADDR, (char*)&reuseaddr, sizeof(reuseaddr)))
{
std::cerr << "Error setting reuse option on socket!" << std::endl;
}
}

/**
* Closes the socket.
*/
void SimpleWindowsUpdSocket::close()
{
if (isOpen_ == false) return;

isOpen_ = false;
::close(connectSocket_);
}

/**
* Sends the data buffer to the previously set address
*/
uint32_t SimpleWindowsUpdSocket::send(std::vector<uint8_t> data, bool isBlocking)
{
if (isOpen_ == false) return 0;

u_long nonblocking = 0;
if (isBlocking == false)
{
nonblocking = 1;
if (ioctlsocket(connectSocket_, FIONBIO, &nonblocking) != 0)
{
std::cerr << "Could not set non-blocking mode on socket!" << std::endl;
}
}

struct sockaddr* address = nullptr;
address = (struct sockaddr*)addressInfo_->ai_addr;


int32_t bytes_sent = ::sendto(connectSocket_, (char*) &data[0], (int) data.size(), 0, address, sizeof(sockaddr_in));
if (bytes_sent == -1)
{
int e = errno;

std::cerr << "Error in sendto: " << e << std::endl;
}

if (isBlocking == false)
{
nonblocking = 0;
if (ioctlsocket(connectSocket_, FIONBIO, &nonblocking) != 0)
{
std::cerr << "Could not set blocking mode on socket!" << std::endl;
}
}

return bytes_sent;
}

/**
* Binds the previously set address as own address to prepare socket for incoming messages.
*/
bool SimpleWindowsUpdSocket::bind()
{
if (isOpen_ == false)
{
std::cerr << "Error: trying to bind a non open socket!" << std::endl;
return false;
}

struct sockaddr* address = nullptr;
address = (struct sockaddr*)addressInfo_->ai_addr;

if (::bind(connectSocket_, address, sizeof(sockaddr_in)) != 0)
{
int e = errno;
std::cerr << "Error binding socket: " << e << std::endl;
return false;
}

return true;
}

/**
* Checks socket connection for incoming messages and stores incoming message in data buffer.
*/
uint32_t SimpleWindowsUpdSocket::receive(std::vector<uint8_t>& data, uint32_t maxSize, bool isBlocking)
{
if (isOpen_ == false) return 0;

struct sockaddr *a;
socklen_t a_len;

sockaddr_in addrIn;
addrIn.sin_port = 0;
addrIn.sin_family = AF_INET;
addrIn.sin_addr.s_addr = htonl(INADDR_ANY);

a = (struct sockaddr*)&addrIn;
a_len = sizeof(sockaddr_in);

u_long nonblocking = 0;
if (isBlocking == false)
{
nonblocking = 1;
if (ioctlsocket(connectSocket_, FIONBIO, &nonblocking) != 0)
{
std::cerr << "Could not set non-blocking mode on socket!" << std::endl;
}
}

uint32_t toread = maxSize ? maxSize : (uint32_t) data.capacity();
if (maxSize > data.capacity())
{
std::cerr << "Data to read over buffer capacity!" << std::endl;
return 0;
}

// Check for timeout, used to terminate thread on application close.
if (select((int) connectSocket_, &socketArray_, NULL, NULL, &timeout_) == 0)
{
return 0;
}

int32_t read_bytes = ::recvfrom(connectSocket_, (char*)&data[0], toread, 0, a, &a_len);

int32_t e = errno;
if (read_bytes == -1 || read_bytes == 0)
{
std::cerr << "Error in recvfrom: " << e << std::endl;
data.clear();
return 0;
}

if (isBlocking == false)
{
nonblocking = 0;
if (ioctlsocket(connectSocket_, FIONBIO, &nonblocking) != 0)
{
std::cerr << "Could not set blocking mode on socket!" << std::endl;
}
}

data.resize(std::max(read_bytes, 0));

return read_bytes;
}