netatalk  4.5.0
Free and Open Source Apple Filing Protocol (AFP) Server
Loading...
Searching...
No Matches
afp_dsi.c File Reference
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <poll.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <atalk/afp_util.h>
#include <atalk/compat.h>
#include <atalk/dsi.h>
#include <atalk/fce_api.h>
#include <atalk/globals.h>
#include <atalk/logger.h>
#include <atalk/netatalk_conf.h>
#include <atalk/server_ipc.h>
#include <atalk/spotlight.h>
#include <atalk/util.h>
#include <atalk/uuid.h>
#include "auth.h"
#include "dircache.h"
#include "directory.h"
#include "fork.h"
#include "idle_worker.h"
#include "switch.h"

Data Structures

struct  rc_elem_t

Macros

#define SOL_TCP   IPPROTO_TCP

Functions

static void sigpipe_init (void)
static void sigpipe_notify (void)
 Write a single byte to the self-pipe.
static void sigpipe_drain (void)
 Drain all pending bytes from the self-pipe.
static void afp_dsi_close (AFPObj *obj)
static void afp_dsi_die (int sig)
 SIGTERM: Terminate the AFP session and exit.
static void afp_dsi_transfer_handler (int sig)
static void handle_transfer_session (AFPObj *obj)
 Process deferred SIGURG: primary reconnect.
static void afp_dsi_die_handler (int sig)
static void afp_dsi_timedown_handler (int sig)
static void handle_timedown (AFPObj *obj)
 Process deferred SIGUSR1: server going down in 5 minutes.
static void afp_dsi_reload (int sig)
static void afp_dsi_debug (int sig)
static void afp_dsi_getmesg_handler (int sig)
static void handle_getmesg (AFPObj *obj)
 Process deferred SIGUSR2: server message.
static void alarm_handler (int sig)
 SIGALRM handler — async-signal-safe.
static void handle_alarm (AFPObj *obj)
 Process deferred SIGALRM: tickle/timeout management.
static void child_handler (int sig)
static int process_deferred_signals (AFPObj *obj)
 Process all pending deferred signals.
static void pending_request (DSI *dsi)
void afp_over_dsi_sighandlers (AFPObj *obj)
void afp_over_dsi (AFPObj *obj)

Variables

AFPObjAFPobj = NULL
static rc_elem_t replaycache [REPLAYCACHE_SIZE]
static volatile sig_atomic_t alarm_pending = 0
static volatile sig_atomic_t transfer_pending = 0
static volatile sig_atomic_t timedown_pending = 0
static volatile sig_atomic_t getmesg_pending = 0
volatile sig_atomic_t die_pending = 0
static int sigpipe_fd [2] = {-1, -1}
 Self-pipe for waking poll() from signal handlers.
volatile sig_atomic_t reload_request = 0
static volatile sig_atomic_t debug_request = 0

Macro Definition Documentation

◆ SOL_TCP

#define SOL_TCP   IPPROTO_TCP

Function Documentation

◆ afp_dsi_close()

void afp_dsi_close ( AFPObj * obj)
static

◆ afp_dsi_debug()

void afp_dsi_debug ( int sig)
static

◆ afp_dsi_die()

void afp_dsi_die ( int sig)
static

SIGTERM: Terminate the AFP session and exit.

Wraps afp_dsi_close() + exit() with pre-flight checks and a shutdown attention to notify the client. Other call sites in this file invoke afp_dsi_close() + exit() directly — a future cleanup could funnel all exit paths through here.

Parameters
sigsignal number or EXITERR_* code; 0 for maintenance shutdown.

◆ afp_dsi_die_handler()

void afp_dsi_die_handler ( int sig)
static

SIGTERM/SIGQUIT handler — async-signal-safe

◆ afp_dsi_getmesg_handler()

void afp_dsi_getmesg_handler ( int sig)
static

SIGUSR2 handler — async-signal-safe

◆ afp_dsi_reload()

void afp_dsi_reload ( int sig)
static

◆ afp_dsi_timedown_handler()

void afp_dsi_timedown_handler ( int sig)
static

SIGUSR1 handler — async-signal-safe

◆ afp_dsi_transfer_handler()

void afp_dsi_transfer_handler ( int sig)
static

SIGURG handler (primary reconnect) — async-signal-safe

◆ afp_over_dsi()

void afp_over_dsi ( AFPObj * obj)

◆ afp_over_dsi_sighandlers()

void afp_over_dsi_sighandlers ( AFPObj * obj)

◆ alarm_handler()

void alarm_handler ( int sig)
static

SIGALRM handler — async-signal-safe.

Only restarts the timer (setitimer is async-signal-safe) and sets a flag. All tickle/timeout logic is deferred to handle_alarm().

◆ child_handler()

void child_handler ( int sig)
static

◆ handle_alarm()

void handle_alarm ( AFPObj * obj)
static

Process deferred SIGALRM: tickle/timeout management.

Called from the main event loop where LOG/malloc/syslog are safe.

◆ handle_getmesg()

void handle_getmesg ( AFPObj * obj)
static

Process deferred SIGUSR2: server message.

Called from the main event loop.

◆ handle_timedown()

void handle_timedown ( AFPObj * obj)
static

Process deferred SIGUSR1: server going down in 5 minutes.

Called from the main event loop.

◆ handle_transfer_session()

void handle_transfer_session ( AFPObj * obj)
static

Process deferred SIGURG: primary reconnect.

Called from the main event loop where non-signal-safe functions are permitted.

◆ pending_request()

void pending_request ( DSI * dsi)
static

◆ process_deferred_signals()

int process_deferred_signals ( AFPObj * obj)
static

Process all pending deferred signals.

Returns
1 if the caller should restart the outer event loop (primary reconnect), 0 otherwise.
Note
Must be called from the main event loop, never from signal context.

◆ sigpipe_drain()

void sigpipe_drain ( void )
static

Drain all pending bytes from the self-pipe.

Called from the main loop after poll() returns.

◆ sigpipe_init()

void sigpipe_init ( void )
static

◆ sigpipe_notify()

void sigpipe_notify ( void )
static

Write a single byte to the self-pipe.

Called from signal handlers — async-signal-safe.

Variable Documentation

◆ AFPobj

AFPObj* AFPobj = NULL

We generally pass this from afp_over_dsi to all afp_* funcs, so it should already be available everywhere. Unfortunately some funcs (eg acltoownermode) need acces to it but are deeply nested in the function chain with the caller already without acces to it. Changing this would require adding a reference to the caller which itself might be called in many places (eg acltoownermode is called from accessmode). The only sane way out is providing a copy of it here:

◆ alarm_pending

volatile sig_atomic_t alarm_pending = 0
static

◆ debug_request

volatile sig_atomic_t debug_request = 0
static

SIGINT: enable max_debug LOGging — async-signal-safe

◆ die_pending

volatile sig_atomic_t die_pending = 0

◆ getmesg_pending

volatile sig_atomic_t getmesg_pending = 0
static

◆ reload_request

volatile sig_atomic_t reload_request = 0

SIGHUP: reload configuration file — async-signal-safe

◆ replaycache

rc_elem_t replaycache[REPLAYCACHE_SIZE]
static

AFP replay cache:

  • fix sized array
  • indexed just by taking DSIreqID mod REPLAYCACHE_SIZE

◆ sigpipe_fd

int sigpipe_fd[2] = {-1, -1}
static

Self-pipe for waking poll() from signal handlers.

Signal handlers write a single byte to sigpipe_fd[1]. The read end sigpipe_fd[0] is included in the poll() set so that the main loop wakes up promptly even when SA_RESTART would otherwise cause poll() to be restarted transparently.

Although POSIX says poll() is not affected by SA_RESTART, some platforms (Solaris, illumos) have historically restarted it. The self-pipe makes wake-up behaviour portable and deterministic.

◆ timedown_pending

volatile sig_atomic_t timedown_pending = 0
static

◆ transfer_pending

volatile sig_atomic_t transfer_pending = 0
static