Permalink
Browse files

Systemd support.

  • Loading branch information...
1 parent 7e42fe6 commit 1eb151f58ccf8d9b691b8500b7fdeb09ceb6ec7b @davidmoreno committed Sep 18, 2011
Showing with 117 additions and 60 deletions.
  1. +14 −1 CMakeLists.txt
  2. +19 −0 README.rst
  3. +1 −1 examples/oterm/oterm.c
  4. +1 −1 examples/oterm/oterm.service
  5. +1 −1 examples/userver/userver.c
  6. +6 −2 src/onion/CMakeLists.txt
  7. +67 −49 src/onion/onion.c
  8. +8 −5 src/onion/types.h
View
@@ -8,6 +8,7 @@ SET(ONION_USE_PAM true)
SET(ONION_USE_PTHREADS true)
SET(ONION_USE_PNG true)
SET(ONION_USE_XML2 true)
+SET(ONION_USE_SYSTEMD true)
SET(ONION_VERSION 0.4.0)
########
@@ -100,6 +101,16 @@ else(CURL_LIB)
message("curl not found. Some examples wil not be built.")
endif(CURL_LIB)
+if (${ONION_USE_SYSTEMD})
+ find_library(RT_LIB NAMES rt PATH ${LIBPATH})
+ if (RT_LIB)
+ set(SYSTEMD_ENABLED true)
+ message(STATUS "librt found. Systemd support compiled in.")
+ else(RT_LIB)
+ message("librt not found. Systemd support is not compiled in.")
+ endif(RT_LIB)
+endif(${ONION_USE_SYSTEMD})
+
# defines
if (GNUTLS_ENABLED)
@@ -114,7 +125,9 @@ endif(PAM_ENABLED)
if (XML2_ENABLED)
add_definitions(-DHAVE_WEBDAV)
endif(XML2_ENABLED)
-
+if (SYSTEMD_ENABLED)
+ add_definitions(-DHAVE_SYSTEMD)
+endif (SYSTEMD_ENABLED)
##
IF (${CMAKE_BUILD_TYPE} MATCHES "Debug")
View
@@ -101,3 +101,22 @@ I18N
----
There is I18N support. Check wiki for details or fileserver_otemplate example.
+
+Systemd
+-------
+
+Systemd is integrated. If want to use it, just pass the flag O_SYSTEMD to the onion_new().
+
+Oterm has example socket and service files for oterm support.
+
+Binary compatibility breaks
+---------------------------
+
+We try hard to keep binary compatibility, but sometimes its hard. Here is a list of ABI breaks:
+
+>0.4.0
+''''''
+
+* Onion object private flags have moved. If on your code you rely on them, must recompile. If
+ dont rely on them, everything should keep working.
+
View
@@ -180,7 +180,7 @@ int main(int argc, char **argv){
#endif
oterm=onion_handler_new((void*)oterm_nopam, url, (void*)onion_handler_free);
- o=onion_new(O_THREADED);
+ o=onion_new(O_THREADED|O_SYSTEMD);
onion_set_root_handler(o, oterm);
if (!(onion_flags(o)&O_SSL_AVAILABLE)){
@@ -1,3 +1,3 @@
[Service]
-ExecStart=/usr/bin/oterm
+ExecStart=/usr/local/bin/oterm
@@ -53,7 +53,7 @@ int main(int argc, char **argv){
onion_handler *dir=onion_handler_export_local_new(dirname);
onion_handler_add(dir, onion_handler_static("<h1>404 - File not found.</h1>", 404) );
- o=onion_new(O_THREADED|O_DETACH_LISTEN);
+ o=onion_new(O_THREADED|O_DETACH_LISTEN|O_SYSTEMD);
onion_set_root_handler(o, dir);
View
@@ -1,10 +1,10 @@
# the lib itself. Two versions, static and shared.
add_library(onion SHARED codecs.c dict.c onion.c request.c request_parser.c response.c handler.c
- server.c log.c sessions.c shortcuts.c block.c mime.c url.c)
+ server.c log.c sessions.c shortcuts.c block.c mime.c url.c sd-daemon.c)
add_library(onion_static STATIC codecs.c dict.c onion.c request.c request_parser.c response.c handler.c
- server.c log.c sessions.c shortcuts.c block.c mime.c url.c)
+ server.c log.c sessions.c shortcuts.c block.c mime.c url.c sd-daemon.c)
# library dependencies
@@ -16,6 +16,10 @@ if (PTHREADS)
target_link_libraries(onion pthread)
target_link_libraries(onion_static pthread)
endif(PTHREADS)
+if (SYSTEMD_ENABLED)
+ target_link_libraries(onion ${RT_LIB})
+ target_link_libraries(onion_static ${RT_LIB})
+endif(SYSTEMD_ENABLED)
add_subdirectory(handlers)
View
@@ -184,6 +184,10 @@ GCRY_THREAD_OPTION_PTHREAD_IMPL;
#include <pwd.h>
#include <grp.h>
+#ifdef HAVE_SYSTEMD
+#include "sd-daemon.h"
+#endif
+
#ifndef SOCK_CLOEXEC
#define SOCK_CLOEXEC 0
#define accept4(a,b,c,d) accept(a,b,c);
@@ -336,56 +340,74 @@ int onion_listen(onion *o){
}
#endif
- int sockfd;
- struct addrinfo hints;
- struct addrinfo *result, *rp;
- struct sockaddr_storage cli_addr;
-
- memset(&hints,0, sizeof(struct addrinfo));
- hints.ai_canonname=NULL;
- hints.ai_addr=NULL;
- hints.ai_next=NULL;
- hints.ai_socktype=SOCK_STREAM;
- hints.ai_family=AF_UNSPEC;
- hints.ai_flags=AI_PASSIVE|AI_NUMERICSERV;
-
- if (getaddrinfo(o->hostname, o->port, &hints, &result) !=0 ){
- ONION_ERROR("Error getting local address and port: %s", strerror(errno));
- return errno;
+ int sockfd=0;
+#ifdef HAVE_SYSTEMD
+ if (o->flags&O_SYSTEMD){
+ int n=sd_listen_fds(0);
+ ONION_DEBUG("Checking if have systemd sockets: %d",n);
+ if (n>0){ // If 0, normal startup. Else use the first LISTEN_FDS.
+ ONION_DEBUG("Using systemd sockets");
+ if (n>1){
+ ONION_WARNING("Get more than one systemd socket descriptor. Using only the first.");
+ }
+ sockfd=SD_LISTEN_FDS_START+0;
+ }
}
-
- int optval=1;
- for(rp=result;rp!=NULL;rp=rp->ai_next){
- sockfd=socket(rp->ai_family, rp->ai_socktype | SOCK_CLOEXEC, rp->ai_protocol);
- if(SOCK_CLOEXEC == 0) { // Good compiler know how to cut this out
- int flags=fcntl(sockfd, F_GETFD);
- if (flags==-1){
- ONION_ERROR("Retrieving flags from listen socket");
+#endif
+ struct sockaddr_storage cli_addr;
+ char address[64];
+ if (sockfd==0){
+ struct addrinfo hints;
+ struct addrinfo *result, *rp;
+
+ memset(&hints,0, sizeof(struct addrinfo));
+ hints.ai_canonname=NULL;
+ hints.ai_addr=NULL;
+ hints.ai_next=NULL;
+ hints.ai_socktype=SOCK_STREAM;
+ hints.ai_family=AF_UNSPEC;
+ hints.ai_flags=AI_PASSIVE|AI_NUMERICSERV;
+
+ if (getaddrinfo(o->hostname, o->port, &hints, &result) !=0 ){
+ ONION_ERROR("Error getting local address and port: %s", strerror(errno));
+ return errno;
+ }
+
+ int optval=1;
+ for(rp=result;rp!=NULL;rp=rp->ai_next){
+ sockfd=socket(rp->ai_family, rp->ai_socktype | SOCK_CLOEXEC, rp->ai_protocol);
+ if(SOCK_CLOEXEC == 0) { // Good compiler know how to cut this out
+ int flags=fcntl(sockfd, F_GETFD);
+ if (flags==-1){
+ ONION_ERROR("Retrieving flags from listen socket");
+ }
+ flags|=FD_CLOEXEC;
+ if (fcntl(sockfd, F_SETFD, flags)==-1){
+ ONION_ERROR("Setting O_CLOEXEC to listen socket");
+ }
}
- flags|=FD_CLOEXEC;
- if (fcntl(sockfd, F_SETFD, flags)==-1){
- ONION_ERROR("Setting O_CLOEXEC to listen socket");
+ if (sockfd<0) // not valid
+ continue;
+ if (setsockopt(sockfd,SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval) ) < 0){
+ ONION_ERROR("Could not set socket options: %s",strerror(errno));
}
+ if (bind(sockfd, rp->ai_addr, rp->ai_addrlen) == 0)
+ break; // Success
+ close(sockfd);
}
- if (sockfd<0) // not valid
- continue;
- if (setsockopt(sockfd,SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval) ) < 0){
- ONION_ERROR("Could not set socket options: %s",strerror(errno));
+ if (rp==NULL){
+ ONION_ERROR("Could not find any suitable address to bind to.");
+ return errno;
}
- if (bind(sockfd, rp->ai_addr, rp->ai_addrlen) == 0)
- break; // Success
- close(sockfd);
- }
- if (rp==NULL){
- ONION_ERROR("Could not find any suitable address to bind to.");
- return errno;
+ freeaddrinfo(result);
+
+ getnameinfo(rp->ai_addr, rp->ai_addrlen, address, 32,
+ &address[32], 32, NI_NUMERICHOST | NI_NUMERICSERV);
+ ONION_DEBUG("Listening to %s:%s",address,&address[32]);
+
+ listen(sockfd,5); // queue of only 5.
}
- char address[64];
- getnameinfo(rp->ai_addr, rp->ai_addrlen, address, 32,
- &address[32], 32, NI_NUMERICHOST | NI_NUMERICSERV);
- ONION_DEBUG("Listening to %s:%s",address,&address[32]);
-
// Drops priviledges as it has binded.
if (o->username){
struct passwd *pw;
@@ -405,12 +427,8 @@ int onion_listen(onion *o){
return errno;
}
}
-
- listen(sockfd,5); // queue of only 5.
-
- freeaddrinfo(result);
-
- socklen_t clilen = sizeof(cli_addr);
+
+ socklen_t clilen = sizeof(cli_addr);
if (o->flags&O_ONE){
int clientfd;
View
@@ -121,14 +121,17 @@ enum onion_mode_e{
O_ONE_LOOP=3, ///< Perform one petition at a time; lineal processing
O_THREADED=4, ///< Threaded processing, process many petitions at a time. Needs pthread support.
O_DETACH_LISTEN=8, ///< When calling onion_listen, it returns inmediatly and do the listening on another thread. Only if threading is available.
+ O_SYSTEMD=0x010, ///< Allow to start as systemd service. It try to start as if from systemd, but if not, start normally, so its "transparent".
- O_SSL_AVAILABLE=0x10, ///< This is set by the library when creating the onion object, if SSL support is available.
- O_SSL_ENABLED=0x20, ///< This is set by the library when setting the certificates, if SSL is available.
+ /// @{ @name From here on, they are internal. User may check them, but not set.
+ O_SSL_AVAILABLE=0x0100, ///< This is set by the library when creating the onion object, if SSL support is available.
+ O_SSL_ENABLED=0x0200, ///< This is set by the library when setting the certificates, if SSL is available.
- O_THREADS_AVALIABLE=0x40, ///< Threads are available on this onion build
- O_THREADS_ENABLED=0x80, ///< Threads are enabled on this onion object. It difers from O_THREADED as this is set by the library, so it states a real status, not a desired one.
+ O_THREADS_AVALIABLE=0x0400, ///< Threads are available on this onion build
+ O_THREADS_ENABLED=0x0800, ///< Threads are enabled on this onion object. It difers from O_THREADED as this is set by the library, so it states a real status, not a desired one.
- O_DETACHED=0x0100, ///< Currently listening on another thread.
+ O_DETACHED=0x01000, ///< Currently listening on another thread.
+ /// @}
};
typedef enum onion_mode_e onion_mode;

0 comments on commit 1eb151f

Please sign in to comment.