Skip to content
This repository was archived by the owner on Jan 1, 2024. It is now read-only.

Commit 4b16bbb

Browse files
authored
Merge pull request #4 from tobbenb/telldus
Add tellstick compiling in Dockerfile
2 parents 382f4a5 + 152e125 commit 4b16bbb

File tree

7 files changed

+293
-169
lines changed

7 files changed

+293
-169
lines changed

Dockerfile

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DA
1010
ENV HOME="/config"
1111

1212
# copy prebuilds
13-
COPY prebuilds/ /usr/
13+
COPY patches/ /
1414

1515
# install build dependencies
1616
RUN \
@@ -37,10 +37,51 @@ RUN \
3737
tar \
3838
zlib-dev && \
3939

40+
# install telldus-core build-dependencies
41+
apk add --no-cache --virtual=telldus-build-dependencies \
42+
argp-standalone \
43+
binutils \
44+
confuse-dev \
45+
curl \
46+
gzip && \
47+
48+
# install telldus-core build-dependencies from edge
49+
apk add --no-cache --virtual=telldus-build-dependencies-edge \
50+
--repository http://nl.alpinelinux.org/alpine/edge/community \
51+
doxygen \
52+
libftdi1-dev && \
53+
54+
4055
# add runtime packages required in build stage
4156
apk add --no-cache \
4257
python3-dev && \
4358

59+
# link libftdi as the alpine guys named the libs wrong
60+
ln -s /usr/lib/libftdi1.so /usr/lib/libftdi.so && \
61+
ln -s /usr/lib/libftdi1.a /usr/lib/libftdi.a && \
62+
ln -s /usr/include/libftdi1/ftdi.h /usr/include/ftdi.h && \
63+
64+
# build telldus-core
65+
mkdir -p \
66+
/tmp/telldus-core && \
67+
curl -o /tmp/telldus-core.tar.gz -L \
68+
http://download.telldus.se/TellStick/Software/telldus-core/telldus-core-2.1.2.tar.gz && \
69+
tar xf /tmp/telldus-core.tar.gz -C \
70+
/tmp/telldus-core --strip-components=1 && \
71+
curl -o /tmp/telldus-core/Doxyfile.in -L \
72+
https://raw.githubusercontent.com/telldus/telldus/master/telldus-core/Doxyfile.in && \
73+
cp /tmp/patches/Socket_unix.cpp /tmp/telldus-core/common/Socket_unix.cpp && \
74+
cp /tmp/patches/ConnectionListener_unix.cpp /tmp/telldus-core/service/ConnectionListener_unix.cpp && \
75+
cd /tmp/telldus-core && \
76+
cmake -DBUILD_TDADMIN=false -DCMAKE_INSTALL_PREFIX=/tmp/telldus-core . && \
77+
make && \
78+
79+
# move needed telldus core files and link them
80+
mv /tmp/telldus-core/client/libtelldus-core.so.2.1.2 /usr/lib/libtelldus-core.so.2.1.2 && \
81+
mv /tmp/telldus-core/client/telldus-core.h /usr/include/telldus-core.h && \
82+
ln -s /usr/lib/libtelldus-core.so.2.1.2 /usr/lib/libtelldus-core.so.2 && \
83+
ln -s /usr/lib/libtelldus-core.so.2 /usr/lib/libtelldus-core.so && \
84+
4485
# build OpenZWave
4586
git clone https://github.com/OpenZWave/open-zwave.git /tmp/open-zwave && \
4687
ln -s /tmp/open-zwave /tmp/open-zwave-read-only && \
@@ -86,15 +127,19 @@ cmake \
86127

87128
# cleanup build dependencies
88129
apk del --purge \
89-
build-dependencies && \
130+
build-dependencies \
131+
telldus-build-dependencies \
132+
telldus-build-dependencies-edge && \
90133

91134

92135
# add abc to dialout and cron group trying to fix different GID for dialout group
93136
usermod -a -G 16,20 abc && \
94137

95138
# cleanup /tmp
96139
rm -rf \
97-
/tmp/*
140+
/tmp/* \
141+
/usr/lib/libftdi* \
142+
/usr/include/ftdi.h
98143

99144
# copy local files
100145
COPY root/ /
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
//
2+
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
3+
//
4+
// Copyright: See COPYING file that comes with this distribution
5+
//
6+
//
7+
#include <sys/socket.h>
8+
#include <sys/un.h>
9+
#include <sys/types.h>
10+
#include <sys/stat.h>
11+
#include <stdio.h>
12+
#include <unistd.h>
13+
#include <fcntl.h>
14+
#include <errno.h>
15+
#include <string.h>
16+
17+
#include "service/ConnectionListener.h"
18+
#include "common/Socket.h"
19+
20+
#if defined(_MACOSX) && !defined(SOCK_CLOEXEC)
21+
#define SOCK_CLOEXEC 0
22+
#endif
23+
24+
class ConnectionListener::PrivateData {
25+
public:
26+
TelldusCore::EventRef waitEvent;
27+
std::string name;
28+
bool running;
29+
};
30+
31+
ConnectionListener::ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent) {
32+
d = new PrivateData;
33+
d->waitEvent = waitEvent;
34+
35+
d->name = "/tmp/" + std::string(name.begin(), name.end());
36+
d->running = true;
37+
38+
this->start();
39+
}
40+
41+
ConnectionListener::~ConnectionListener(void) {
42+
d->running = false;
43+
this->wait();
44+
unlink(d->name.c_str());
45+
delete d;
46+
}
47+
48+
void ConnectionListener::run() {
49+
struct timeval tv = { 0, 0 };
50+
51+
// Timeout for select
52+
53+
SOCKET_T serverSocket;
54+
struct sockaddr_un name;
55+
serverSocket = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
56+
if (serverSocket < 0) {
57+
return;
58+
}
59+
#if defined(_MACOSX)
60+
int op = fcntl(serverSocket, F_GETFD);
61+
fcntl(serverSocket, F_SETFD, op | FD_CLOEXEC); // OS X doesn't support SOCK_CLOEXEC yet
62+
#endif
63+
name.sun_family = AF_LOCAL;
64+
memset(name.sun_path, '\0', sizeof(name.sun_path));
65+
strncpy(name.sun_path, d->name.c_str(), sizeof(name.sun_path));
66+
unlink(name.sun_path);
67+
int size = SUN_LEN(&name);
68+
bind(serverSocket, (struct sockaddr *)&name, size);
69+
listen(serverSocket, 5);
70+
71+
// Change permissions to allow everyone
72+
chmod(d->name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
73+
74+
fd_set infds;
75+
FD_ZERO(&infds);
76+
FD_SET(serverSocket, &infds);
77+
78+
while(d->running) {
79+
tv.tv_sec = 5;
80+
81+
int response = select(serverSocket+1, &infds, NULL, NULL, &tv);
82+
if (response == 0) {
83+
FD_SET(serverSocket, &infds);
84+
continue;
85+
} else if (response < 0 ) {
86+
continue;
87+
}
88+
// Make sure it is a new connection
89+
if (!FD_ISSET(serverSocket, &infds)) {
90+
continue;
91+
}
92+
SOCKET_T clientSocket = accept(serverSocket, NULL, NULL);
93+
94+
ConnectionListenerEventData *data = new ConnectionListenerEventData();
95+
data->socket = new TelldusCore::Socket(clientSocket);
96+
d->waitEvent->signal(data);
97+
}
98+
close(serverSocket);
99+
}
100+

patches/tmp/patches/Socket_unix.cpp

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
//
2+
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
3+
//
4+
// Copyright: See COPYING file that comes with this distribution
5+
//
6+
//
7+
8+
#include <stdio.h>
9+
#include <unistd.h>
10+
#include <sys/socket.h>
11+
#include <sys/select.h>
12+
#include <sys/un.h>
13+
#include <fcntl.h>
14+
#include <math.h>
15+
#include <string.h>
16+
17+
#include "common/Socket.h"
18+
#include "common/Mutex.h"
19+
#include "common/Strings.h"
20+
21+
#define BUFSIZE 512
22+
#if defined(_MACOSX) && !defined(SOCK_CLOEXEC)
23+
#define SOCK_CLOEXEC 0
24+
#endif
25+
26+
namespace TelldusCore {
27+
28+
int connectWrapper(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
29+
return connect(sockfd, addr, addrlen);
30+
}
31+
32+
class Socket::PrivateData {
33+
public:
34+
SOCKET_T socket;
35+
bool connected;
36+
fd_set infds;
37+
Mutex mutex;
38+
};
39+
40+
Socket::Socket() {
41+
d = new PrivateData;
42+
d->socket = 0;
43+
d->connected = false;
44+
FD_ZERO(&d->infds);
45+
}
46+
47+
Socket::Socket(SOCKET_T socket) {
48+
d = new PrivateData;
49+
d->socket = socket;
50+
FD_ZERO(&d->infds);
51+
d->connected = true;
52+
}
53+
54+
Socket::~Socket(void) {
55+
if(d->socket) {
56+
close(d->socket);
57+
}
58+
delete d;
59+
}
60+
61+
void Socket::connect(const std::wstring &server) {
62+
struct sockaddr_un remote;
63+
socklen_t len;
64+
65+
if ((d->socket = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) == -1) {
66+
return;
67+
}
68+
#if defined(_MACOSX)
69+
int op = fcntl(d->socket, F_GETFD);
70+
fcntl(d->socket, F_SETFD, op | FD_CLOEXEC); // OS X doesn't support SOCK_CLOEXEC yet
71+
#endif
72+
std::string name = "/tmp/" + std::string(server.begin(), server.end());
73+
remote.sun_family = AF_UNIX;
74+
snprintf(remote.sun_path, sizeof(remote.sun_path), "%s", name.c_str());
75+
76+
len = SUN_LEN(&remote);
77+
if (connectWrapper(d->socket, (struct sockaddr *)&remote, len) == -1) {
78+
return;
79+
}
80+
81+
TelldusCore::MutexLocker locker(&d->mutex);
82+
d->connected = true;
83+
}
84+
85+
bool Socket::isConnected() {
86+
TelldusCore::MutexLocker locker(&d->mutex);
87+
return d->connected;
88+
}
89+
90+
std::wstring Socket::read() {
91+
return this->read(0);
92+
}
93+
94+
std::wstring Socket::read(int timeout) {
95+
struct timeval tv;
96+
char inbuf[BUFSIZE];
97+
98+
FD_SET(d->socket, &d->infds);
99+
std::string msg;
100+
while(isConnected()) {
101+
tv.tv_sec = floor(timeout / 1000.0);
102+
tv.tv_usec = timeout % 1000;
103+
104+
int response = select(d->socket+1, &d->infds, NULL, NULL, &tv);
105+
if (response == 0 && timeout > 0) {
106+
return L"";
107+
} else if (response <= 0) {
108+
FD_SET(d->socket, &d->infds);
109+
continue;
110+
}
111+
112+
int received = BUFSIZE;
113+
while(received >= (BUFSIZE - 1)) {
114+
memset(inbuf, '\0', sizeof(inbuf));
115+
received = recv(d->socket, inbuf, BUFSIZE - 1, 0);
116+
if(received > 0) {
117+
msg.append(std::string(inbuf));
118+
}
119+
}
120+
if (received < 0) {
121+
TelldusCore::MutexLocker locker(&d->mutex);
122+
d->connected = false;
123+
}
124+
break;
125+
}
126+
127+
return TelldusCore::charToWstring(msg.c_str());
128+
}
129+
130+
void Socket::stopReadWait() {
131+
TelldusCore::MutexLocker locker(&d->mutex);
132+
d->connected = false;
133+
// TODO(stefan): somehow signal the socket here?
134+
}
135+
136+
void Socket::write(const std::wstring &msg) {
137+
std::string newMsg(TelldusCore::wideToString(msg));
138+
int sent = send(d->socket, newMsg.c_str(), newMsg.length(), 0);
139+
if (sent < 0) {
140+
TelldusCore::MutexLocker locker(&d->mutex);
141+
d->connected = false;
142+
}
143+
}
144+
145+
} // namespace TelldusCore

0 commit comments

Comments
 (0)