summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am6
-rw-r--r--src/crosscomposer.cc49
-rw-r--r--src/socket.cc201
-rw-r--r--src/socket.h62
4 files changed, 307 insertions, 11 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index c544e46..db3a5b5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,11 +8,13 @@ crosscomposer_CXXFLAGS = $(ALSA_CFLAGS) $(AO_CFLAGS)
crosscomposer_SOURCES = \
crosscomposer.cc \
audioin.cc \
- audioout.cc
+ audioout.cc \
+ socket.cc
EXTRA_DIST = \
audioin.h \
- audioout.h
+ audioout.h \
+ socket.h
################
# Test Section #
diff --git a/src/crosscomposer.cc b/src/crosscomposer.cc
index c8992ff..010aa92 100644
--- a/src/crosscomposer.cc
+++ b/src/crosscomposer.cc
@@ -27,22 +27,53 @@
*/
#include <stdio.h>
+#include "socket.h"
+
#include "audioin.h"
#include "audioout.h"
+#define NUM_SAMPLES 940
+
int main(int argc, char *argv[])
{
- AudioIn in("default", "Capture", 44101, 1);
- AudioOut out("default", 44101, 1);
-
sample_t samples[940];
- int i = 50;
- while(i--) {
- int sz = in.read(samples, sizeof(samples));
- out.write(samples, sz);
- printf("."); fflush(stdout);
+ Socket s;
+ s.open("127.0.0.1", 10000);
+
+ switch(fork()) {
+ case 0:
+ {
+ AudioIn in("default", "Capture", 44100, 1);
+ s.setSend(0);
+
+ int i = 50;
+ while(i--) {
+ int sz = in.read(samples, NUM_SAMPLES);
+ for(size_t i = 0; i < NUM_SAMPLES; i++) {
+ samples[i] = ((sample_t)rand() / (float)RAND_MAX) * 10;
+ }
+ s.sendTo(samples, sz * sizeof(sample_t));
+ printf("s"); fflush(stdout);
+ }
+ printf("S!\n");
+ }
+ break;
+
+ default:
+ {
+ s.setRecv();
+ AudioOut out("default", 44100, 1);
+
+ int i = 50;
+ while(i--) {
+ int sz = s.recvFrom(samples, sizeof(samples));
+ out.write(samples, sz / sizeof(sample_t));
+ printf("r%f", samples[0]); fflush(stdout);
+ }
+ printf("R!\n");
+ }
+ break;
}
- printf("!\n");
return 0;
}
diff --git a/src/socket.cc b/src/socket.cc
new file mode 100644
index 0000000..b5a93c8
--- /dev/null
+++ b/src/socket.cc
@@ -0,0 +1,201 @@
+/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * File: socket.cc
+ * This file belongs to the Bifrost project.
+ * Socket wrapper class implementation.
+ * Date: Wed Sep 2 09:02:38 CEST 2009
+ * Author: Bent Bisballe Nyeng
+ * Copyright: 2009
+ * Email: deva@aasimon.org
+ ****************************************************************************/
+#include "socket.h"
+
+#include <stdlib.h>
+#include <errno.h>
+
+#ifdef WIN32
+#include <ws2tcpip.h>
+#include <WinSock2.h>
+typedef signed int ssize_t;
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+#define ADDR_IS_MULTICAST(a) IN_MULTICAST(htonl(a))
+
+struct socket_private_t {
+ bool close_socket;
+ socket_t sock;
+ struct sockaddr_in name;
+ struct ip_mreq mreq;
+};
+
+static void leave_group(socket_t sock, struct ip_mreq mreq)
+{
+ int ret;
+
+ ret = setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+ (const char*)&mreq, sizeof(mreq));
+ if (ret < 0) {
+ /*
+ fprintf(stderr, "Failed to leave multicast group.");
+ perror("");
+ */
+ }
+}
+
+
+#ifdef WIN32
+static void wsastartup()
+{
+ WORD wVersionRequested = MAKEWORD(2, 0);
+ WSADATA wsaData;
+
+ int ret = WSAStartup(wVersionRequested, &wsaData);
+ if(ret != 0) throw Socket::WSAException();
+}
+#endif
+
+Socket::Socket()
+ _throw(WSAException)
+{
+ prv = new struct socket_private_t();
+
+#ifdef WIN32
+ wsastartup();
+#endif
+
+ prv->close_socket = false;
+}
+
+Socket::~Socket()
+{
+ if(prv->close_socket) {
+ if (ADDR_IS_MULTICAST(prv->name.sin_addr.s_addr)) {
+ leave_group(prv->sock, prv->mreq);
+ }
+
+#ifdef WIN32
+ closesocket(prv->sock);
+ WSACleanup();
+#else
+ close(prv->sock);
+#endif
+ }
+
+ if(prv) delete prv;
+}
+
+void Socket::open(std::string address, port_t port)
+ _throw(AddressParseException, OpenException)
+{
+ prv->name.sin_family = AF_INET;
+ prv->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if(prv->sock < 0) throw OpenException();
+
+ prv->name.sin_port = htons(port);
+
+#ifdef WIN32
+ prv->name.sin_addr.S_un.S_addr = inet_addr(address.c_str());
+ if(INADDR_NONE == prv->name.sin_addr.S_un.S_addr) throw AddressParseException();
+#else
+ prv->name.sin_addr.s_addr = inet_addr(address.c_str());
+ if(INADDR_NONE == prv->name.sin_addr.s_addr) throw AddressParseException();
+#endif
+
+ prv->close_socket = true;
+}
+
+void Socket::setSocketFiledescriptor(socket_t sock, std::string address, port_t port)
+ _throw(AddressParseException)
+{
+ prv->name.sin_family = AF_INET;
+ prv->sock = sock;
+ if(prv->sock < 0) throw OpenException();
+
+ prv->name.sin_port = htons(port);
+
+#ifdef WIN32
+ prv->name.sin_addr.S_un.S_addr = inet_addr(address.c_str());
+ if(INADDR_NONE == prv->name.sin_addr.S_un.S_addr) throw AddressParseException();
+#else
+ prv->name.sin_addr.s_addr = inet_addr(address.c_str());
+ if(INADDR_NONE == prv->name.sin_addr.s_addr) throw AddressParseException();
+#endif
+
+ prv->close_socket = false;
+}
+
+void Socket::setSend(unsigned char ttl)
+ _throw(MulticastTTLException, MulticastGroupJoinException)
+{
+ int ret;
+ if (ADDR_IS_MULTICAST(prv->name.sin_addr.s_addr)) {
+ ret = setsockopt(prv->sock, IPPROTO_IP, IP_MULTICAST_TTL,
+ (const char*)&ttl, sizeof(ttl));
+ if (ret < 0) throw MulticastTTLException();
+
+ prv->mreq.imr_multiaddr.s_addr = prv->name.sin_addr.s_addr;
+ prv->mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+ ret = setsockopt(prv->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ (const char*)&prv->mreq, sizeof(prv->mreq));
+ if (ret < 0) throw MulticastGroupJoinException();
+ }
+}
+
+void Socket::setRecv()
+ _throw(BindException)
+{
+#ifdef WIN32
+ if(bind(prv->sock, (SOCKADDR*)&prv->name, sizeof(prv->name)) < 0) {
+
+ // int err = WSAGetLastError();
+
+ if(prv->close_socket) closesocket(prv->sock);
+
+ throw BindException();
+ }
+#else
+ if(bind(prv->sock, (struct sockaddr *)&prv->name, sizeof(prv->name)) < 0) {
+
+ if(prv->close_socket) close(prv->sock);
+
+ if(ADDR_IS_MULTICAST(prv->name.sin_addr.s_addr)) {
+ leave_group(prv->sock, prv->mreq);
+ }
+ throw BindException();
+ }
+#endif
+}
+
+size_t Socket::sendTo(void *data, size_t size)
+ _throw(SendException)
+{
+ ssize_t ret = sendto(prv->sock, (const char*) data, size, 0,
+ (struct sockaddr *)&prv->name, sizeof(struct sockaddr_in));
+ if(ret == -1 || (size_t)ret != size) throw SendException();
+ return ret;
+}
+
+size_t Socket::recvFrom(void *data, size_t size)
+ _throw(ReceiveException)
+{
+ ssize_t ret;
+#ifdef WIN32
+ // unsigned long int pending;
+#endif
+
+ // do {
+ ret = recv(prv->sock, (char*) data, size, 0);
+ if(ret == -1) throw ReceiveException();
+#ifdef WIN32
+ // ioctlsocket(prv->sock, FIONREAD, &pending);
+ // } while(pending > 0);
+#else
+ // } while(recv(prv->sock, (char*) data, size, MSG_PEEK | MSG_DONTWAIT) > 0);
+#endif
+ return ret;
+}
+
diff --git a/src/socket.h b/src/socket.h
new file mode 100644
index 0000000..313a87a
--- /dev/null
+++ b/src/socket.h
@@ -0,0 +1,62 @@
+/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * File: socket.h
+ * This file belongs to the Bifrost project.
+ * Socket wrapper class header file.
+ * Date: Wed Sep 2 09:02:38 CEST 2009
+ * Author: Bent Bisballe Nyeng
+ * Copyright: 2009
+ * Email: deva@aasimon.org
+ ****************************************************************************/
+#ifndef __BIFROST_SOCKET_H__
+#define __BIFROST_SOCKET_H__
+
+#include <string>
+#include <exception>
+
+typedef unsigned short int port_t;
+
+#ifdef WIN32
+typedef SOCKET socket_t;
+#define _throw(...)
+#else
+typedef int socket_t;
+#define _throw(fmt...) throw(fmt)
+#endif
+
+struct socket_private_t;
+
+class Socket {
+public:
+ class BindException : public std::exception {};
+ class MulticastTTLException : public std::exception {};
+ class MulticastGroupJoinException : public std::exception {};
+ class ReceiveException : public std::exception {};
+ class SendException : public std::exception {};
+ class WSAException : public std::exception {};
+ class AddressParseException : public std::exception {};
+ class OpenException : public std::exception {};
+
+ Socket() _throw(WSAException);
+ ~Socket();
+
+ void open(std::string address, port_t port)
+ _throw(AddressParseException, OpenException);
+
+ void setSocketFiledescriptor(socket_t sock, std::string address, port_t port)
+ _throw(AddressParseException);
+
+ void setSend(unsigned char ttl)
+ _throw(MulticastTTLException, MulticastGroupJoinException);
+ void setRecv() _throw(BindException);
+
+ virtual size_t sendTo(void *data, size_t size)
+ _throw(SendException);
+ virtual size_t recvFrom(void *data, size_t size)
+ _throw(ReceiveException);
+
+private:
+ struct socket_private_t *prv;
+};
+
+#endif/*__BIFROST_SOCKET_H__*/