summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaromil <jaromil@dyne.org>2008-09-09 13:50:39 (GMT)
committer Jaromil <jaromil@dyne.org>2008-09-09 13:50:39 (GMT)
commitcfa8deed064b4a615c661fcd6ce8702c59a076be (patch)
treeadd1156195c0f931c32f920d69404feffc94bada
parentd87463893e7926e9d4b10b4d0e83747504a575bc (diff)
merge network syncstarting into trunk
udp-lite server thread (cherry picked from commit 3ecbd53b98c19ca6b6a68146ef3f82f466ac6612)
-rw-r--r--Makefile45
-rw-r--r--cmdline.cpp29
-rw-r--r--thread.cpp1
-rw-r--r--udpliteserver.cpp167
-rw-r--r--udpliteserver.h92
5 files changed, 327 insertions, 7 deletions
diff --git a/Makefile b/Makefile
index 422ec59..e35e7b2 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,44 @@
+# We don't need kludgy automatizations here,
+# let's use a simple Makefile.
+# Just tweak the values below to fix your paths
+#
+# $Id: Makefile 60 2004-11-12 15:40:18Z jaromil $
-all:
- # to build run the compile.sh script
+CPP = g++
+LINKER = ld
+
+GTKFLAGS = `pkg-config --cflags gtk+-2.0`
+GTKLIBS = `pkg-config --libs gtk+-2.0`
+
+# debugging flags:
+#CPPFLAGS = -I. -Ixmlrpc++ -Wall -g -ggdb $(GTKFLAGS)
+# optimized flags:
+CPPFLAGS = -I. -Wall -O2 -fomit-frame-pointer -ffast-math $(GTKFLAGS)
+
+
+
+
+LIBS = -lpthread
+
+IVYSYNC_OBJ = decoder.o thread.o linklist.o utils.o cmdline.o gui.o udpliteserver.o
+
+all: ivysync
+
+ivysync: $(IVYSYNC_OBJ)
+ $(CPP) $(CPPFLAGS) -o ivysync $(IVYSYNC_OBJ) $(LIBS) $(GTKLIBS)
+
+#make clean
clean:
- rm -f *.a *.o *~
- rm -f ivysync-nox ivysync-rpc ivysync-gtk xmlrpc++/*.o xmlrpc++/*.a
+ rm -rf *.o *~ ivysync
+
+install: ivysync
+ install ivysync /usr/local/bin
+
+# generic make rules
+#%: %.c
+# $(CC) $(CFLAGS) -o $@ $< $(LIBS)
+#%.o: %.c
+# $(CC) $(CFLAGS) -c -o $@ $<
+
+
diff --git a/cmdline.cpp b/cmdline.cpp
index ff2fad8..16968c3 100644
--- a/cmdline.cpp
+++ b/cmdline.cpp
@@ -43,6 +43,9 @@
#include <gui.h>
#endif
+#ifdef WITH_UDP
+#include <udpliteserver.h>
+#endif
#include <utils.h>
@@ -69,6 +72,11 @@ XmlRpcServer *xmlrpc;
IvySyncDaemon *ivydaemon;
#endif
+#ifdef WITH_UDP
+// UDP lite server
+UdpLiteSrv *udpsrv;
+#endif
+
const char *help =
"Usage: ivysync [-hsDgt] [ -d /dev/video16 [ -p playmode files ] ]\n"
" -h --help show this help\n"
@@ -325,7 +333,6 @@ int main(int argc, char **argv) {
exit(1);
}
////////////////////////////////
-
#endif
#ifdef WITH_XMLRPC
@@ -362,6 +369,13 @@ int main(int argc, char **argv) {
#endif
+#ifdef WITH_UDP
+ udpsrv = new UdpLiteSrv();
+ udpsrv->init(&syncstart);
+ udpsrv->launch();
+#endif
+
+
////////////////////////////////
/// Syncstart!
@@ -384,12 +398,21 @@ int main(int argc, char **argv) {
if( ! rpcdaemon ) {
A("Syncing %i players...",decoders.len());
-
+
+#ifdef WITH_UDP
+ A("waiting for udp signal");
+#else
jsleep(0,500);
+ syncstart = 1;
A("Start!");
+#endif
}
- syncstart = 1;
+
+
+ if(!syncstart) jsleep(0,100);
+
+
////////////////////////////////
diff --git a/thread.cpp b/thread.cpp
index fa1c0ef..a4c221a 100644
--- a/thread.cpp
+++ b/thread.cpp
@@ -30,6 +30,7 @@ bool Thread::launch() {
lock(); // the runner will unlock when ready
return pthread_create(&thread,&attr,&kickoff, this);
lock(); // wait until the thread is ready
+ running = true;
unlock();
}
diff --git a/udpliteserver.cpp b/udpliteserver.cpp
new file mode 100644
index 0000000..b4956d0
--- /dev/null
+++ b/udpliteserver.cpp
@@ -0,0 +1,167 @@
+/* IvySync - Video SyncStarter
+ *
+ * (c) Copyright 2008 Denis Roio aka jaromil <jaromil@dyne.org>
+ * Nederlands Instituut voor Mediakunst
+ *
+ * This source code is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This source code 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.
+ * Please refer to the GNU Public License for more details.
+ *
+ * You should have received a copy of the GNU Public License along with
+ * this source code; if not, write to:
+ * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * to compile this sourcecode: gcc -o ivysync ivysync.c -lpthreads
+ * it should work on any POSIX system, including embedded hardware
+ * wherever the IvyTV drivers can also run (see http://ivtv.sf.net)
+ *
+ */
+
+#include <stdio.h>
+
+#include <stdlib.h> /* exit() */
+#include <unistd.h> /* close() */
+#include <errno.h> /* strerror() */
+#include <string.h> /* memset() */
+
+#include <utils.h>
+#include <udpliteserver.h>
+
+
+
+
+UdpLiteSrv::UdpLiteSrv() {
+ addrlen = sizeof(struct sockaddr_storage);
+ type = v4only; //v6andv4;
+ syncstart = NULL;
+
+ /*
+ * get server IP address
+ */
+ memset(&hints, 0, sizeof(hints)); /* set all unneeded parameters to 0 */
+ sprintf(sbuf, "%d", SERVER_PORT); /* stringify port number */
+ /*
+ * bind socket to server port.
+ * Setting node to NULL in getaddrinfo will result in
+ * --the unspecified (INADDR_ANY | inaddr6_any) address if AI_PASSIVE is set
+ * --the loopback (127.0.0.1 | ::1 ) address if AI_PASSIVE is not set
+ */
+ hints.ai_flags = AI_PASSIVE|AI_NUMERICHOST|AI_ADDRCONFIG;
+ hints.ai_family = (type == v4only)? AF_INET : AF_INET6;
+ hints.ai_socktype = SOCK_DGRAM; /* either UDP or UDP-Lite */
+
+ if(getaddrinfo(NULL, sbuf, &hints, &res) || /* lookup error */
+ res->ai_next != NULL ) /* address ambiguity */
+ E("Can not resolve the server address.");
+
+ /*
+ * Open up the socket
+ */
+ sd = socket(res->ai_family, res->ai_socktype, IPPROTO_UDPLITE);
+ if (sd < 0)
+ E("Cannot open socket.");
+
+#if IPPROTO_UDPLITE
+ /*
+ * Specify the minimum socket coverage required at the receiver.
+ */
+ option = CS_COV;
+ rc = setsockopt(sd, SOL_UDPLITE, UDPLITE_RECV_CSCOV, &option, sizeof(int));
+ if (rc < 0)
+ E("Can not set receiver minimum checksum coverage to %d", option);
+#endif
+ /*
+ * set receive timestamps (returned as cmsg_data)
+ */
+ option = 1;
+ if (setsockopt(sd, SOL_SOCKET, SO_TIMESTAMP, &option, sizeof(option)) < 0)
+ E("Can not set the SO_TIMESTAMP option");
+
+ /*
+ * Restrict to IPv6-only listening if option was given on the commandline
+ */
+ if (type == v6only) {
+ option = 1;
+ rc = setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, &option, sizeof(option));
+ if (rc < 0)
+ E("Can not set the IPV6_V6ONLY option.");
+ }
+
+
+ /*
+ * Bind socket to serving port.
+ */
+ rc = bind(sd, res->ai_addr, res->ai_addrlen);
+ if (rc < 0)
+ E("Cannot bind socket to port number %d", SERVER_PORT);
+
+
+ N("Accepting %s UDP%s connections on port %d",
+ (type == v4only)? "IPv4-only" :
+ (type == v6only)? "IPv6-only" : "IPv4/IPv6",
+ (IPPROTO_UDPLITE > 0)? "-Lite" : "", SERVER_PORT);
+
+}
+
+UdpLiteSrv::~UdpLiteSrv() {
+
+ freeaddrinfo(res);
+
+}
+
+void UdpLiteSrv::init(bool *syncbit) {
+ syncstart = syncbit;
+}
+
+void UdpLiteSrv::run() {
+ /*
+ * server endless loop
+ */
+ memset(buf, 0, sizeof(buf)); /* wipe old buffer contents */
+
+ /* we use recvmsg to get at the flags passed by the kernel */
+ iov[0].iov_base = buf;
+ iov[0].iov_len = sizeof(buf);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = (void *)&cliaddr;
+ msg.msg_namelen = addrlen;
+ msg.msg_controllen = TS_LEN;
+ msg.msg_control = (void *) tsbuf;
+
+ n = recvmsg(sd, &msg, 0);
+
+ if (msg.msg_flags & MSG_TRUNC) /* prepend warning message */
+ W("datagram truncated");
+
+ if (n < 0) /* jump back on error */
+ E("receive problem");
+
+ /* resolve timestamp */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ stamp = (struct timeval *) CMSG_DATA(cmsg);
+ if (!cmsg)
+ W("Failed to get a timestamp for this reception");
+ else
+ A("[%-6lu.%06lu] ", stamp->tv_sec, stamp->tv_usec);
+
+ /* resolve the sender of the message */
+ rc = getnameinfo((struct sockaddr *)&cliaddr, addrlen,
+ hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST|NI_NUMERICSERV);
+ if (rc)
+ W("Can not resolve client address: %s", gai_strerror(rc));
+ else
+ A("from %s on port %s", hbuf, sbuf);
+
+ if(syncstart) *syncstart = true;
+
+}
+
+
+
diff --git a/udpliteserver.h b/udpliteserver.h
new file mode 100644
index 0000000..52b4523
--- /dev/null
+++ b/udpliteserver.h
@@ -0,0 +1,92 @@
+/* IvySync - Video SyncStarter
+ *
+ * (c) Copyright 2008 Denis Roio aka jaromil <jaromil@dyne.org>
+ * Nederlands Instituut voor Mediakunst
+ *
+ * This source code is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This source code 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.
+ * Please refer to the GNU Public License for more details.
+ *
+ * You should have received a copy of the GNU Public License along with
+ * this source code; if not, write to:
+ * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * to compile this sourcecode: gcc -o ivysync ivysync.c -lpthreads
+ * it should work on any POSIX system, including embedded hardware
+ * wherever the IvyTV drivers can also run (see http://ivtv.sf.net)
+ *
+ */
+
+#ifndef __UDPLITESERVER_H__
+#define __UDPLITESERVER_H__
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netdb.h> /* getaddrinfo() */
+#include <arpa/inet.h> /* inet_ntop() */
+#include <netinet/in.h> /* struct sockaddr_in|6 */
+
+
+#include <thread.h>
+
+
+/* CONSTANTS */
+#define CS_COV 8 /* UDP-Lite checksum coverage */
+#define LOCAL_PORT 2000 /* client (sender) port */
+#define SERVER_PORT 15500 /* remote service port */
+/* the following determines the size of packets read from the network */
+#define READSIZE BUFSIZ
+
+#define TS_LEN CMSG_SPACE(sizeof(struct timeval))
+
+// if you comment out the following line, you will get a UDP application
+#undef IPPROTO_UDPLITE
+
+#ifdef IPPROTO_UDPLITE
+#include <netinet/udplite.h> /* definitions for UDP-Lite */
+#else
+#warning "No UDP-Lite support, using UDP instead"
+#define IPPROTO_UDPLITE 0
+#endif
+
+
+class UdpLiteSrv : public Thread {
+
+ public:
+ UdpLiteSrv();
+ ~UdpLiteSrv();
+
+ void run();
+
+ void init(bool *syncbit);
+
+ bool *syncstart;
+
+ private:
+ struct sockaddr_storage cliaddr; /* address of connecting host */
+ socklen_t addrlen; // = sizeof(struct sockaddr_storage);
+
+ struct addrinfo hints, /* address resolution aid */
+ *res; /* resolution results */
+ struct iovec iov[1]; /* scatter/gather array */
+ struct msghdr msg; /* for recvmsg(), see below */
+ struct cmsghdr *cmsg; /* for the timestamp */
+ struct timeval *stamp;
+ char buf[READSIZE], /* read buffer */
+ hbuf[NI_MAXHOST], /* address as string */
+ sbuf[NI_MAXSERV], /* service port as string */
+ tsbuf[TS_LEN]; /* to contain timestamp */
+ int sd, /* socket descriptor */
+ rc, option, n;
+ enum {v6andv4, v4only, v6only} type; // = v6andv4; /* IP service type */
+
+
+};
+
+#endif