Esempio n. 1
0
void
daemon_t::_grandchild(
    pipe_t & c_pipe,
    pipe_t & g_pipe
) {

    try {

        c_pipe.writer().close();

        _init();

        // Initialization finished successfully -- let parent know everything is ok.
        g_pipe.writer().write( ok );
        g_pipe.writer().close();

    } catch ( std::exception const & ex ) {

        g_pipe.writer().write( string_t( ex.what() ) + "\n" );
        throw;

    } catch ( ... ) {

        g_pipe.writer().write( "Unknown exception occurred\n" );
        throw;

    }; // try

    _body();

}; // _grandchild
Esempio n. 2
0
pipe_t pipe_free(pipe_t p)
{
  free(p->type);
  if(p->id) free(p->id);
  if(p->path) lob_free(p->path);
  if(p->notify) LOG("pipe free'd leaking notifications");
  if(p->free) p->free(p);
  free(p);
  return NULL;
}
Esempio n. 3
0
// safe wrapper around ->send
pipe_t pipe_send(pipe_t pipe, lob_t packet, link_t link)
{
  if(!pipe || !packet) return NULL;
  if(!pipe->send || pipe->down)
  {
    LOG("dropping packet to down pipe %s: %s",pipe->id, lob_json(packet));
    lob_free(packet);
    return pipe;
  }
  pipe->send(pipe, packet, link);
  return pipe;
}
Esempio n. 4
0
// encrypt and send this one packet on this pipe
link_t link_direct(link_t link, lob_t inner, pipe_t pipe)
{
  if(!link || !inner) return LOG("bad args");
  if(!pipe && (!link->pipes || !(pipe = link->pipes->pipe))) return LOG("no network");

  // add an outgoing cid if none set
  if(!lob_get_int(inner,"c")) lob_set_uint(inner,"c",e3x_exchange_cid(link->x, NULL));

  pipe->send(pipe, e3x_exchange_send(link->x, inner), link);
  
  return link;
}
Esempio n. 5
0
File: link.c Progetto: fd/telehash-c
// process an incoming handshake
link_t link_handshake(link_t link, lob_t inner, lob_t outer, pipe_t pipe)
{
  link_t ready;
  uint32_t out;

  if(!link || !inner || !outer) return LOG("bad args");
  if(!link->key && link_key(link->mesh,inner) != link) return LOG("invalid/mismatch handshake key");
  out = exchange3_out(link->x,0);
  ready = link_ready(link);

  // if bad at, always send current handshake
  if(exchange3_in(link->x, lob_get_int(inner,"at")) < out)
  {
    LOG("old/bad at: %s (%d,%d,%d)",lob_json(inner),lob_get_int(inner,"at"),exchange3_in(link->x,0),exchange3_out(link->x,0));
    if(pipe) pipe->send(pipe,exchange3_handshake(link->x),link);
    return NULL;
  }

  // trust/add this pipe
  if(pipe) link_pipe(link,pipe);

  // try to sync ephemeral key
  if(!exchange3_sync(link->x,outer)) return LOG("sync failed");
  
  // we may need to re-sync
  if(out != exchange3_out(link->x,0)) link_sync(link);
  
  // notify of ready state change
  if(!ready && link_ready(link))
  {
    LOG("link ready");
    mesh_link(link->mesh, link);
  }
  
  return link;
}
Esempio n. 6
0
void
daemon_t::_child(
    pipe_t &    c_pipe,
    pipe_t &    g_pipe
) {

    try {

        int error = -1;

        c_pipe.reader().close();
        g_pipe.reader().close();

        // Reopen standard streams.
        // Associate all the standard streams with `/dev/null'.
        file_t null( * this );
        null.open( "/dev/null", O_RDONLY, 0 );
        error = dup2( null.fd(), STDIN_FILENO );
        SYSERR( error < 0, "dup2", "Reopening stdin" );
        null.close();
        null.open( "/dev/null", O_WRONLY, 0 );
        error = dup2( null.fd(), STDOUT_FILENO );
        SYSERR( error < 0, "dup2", "Reopening stdout" );
        error = dup2( null.fd(), STDERR_FILENO );
        SYSERR( error < 0, "dup2", "Reopening stderr" );
        null.close();

        pid_t sid = 0;

        ESYSCALL(
            "creating session",
            "setsid",
            sid = setsid(),
            sid > 0,
            "session " << sid << " created"
        );

        // Ignore unused signals.
        // We ignore signals in child so in grandchild these signals are fro the very beginning.
        // If daemon need any of these signals, it will handle them explicitly.
        thread_t::ignore_signal( SIGHUP   );
        thread_t::ignore_signal( SIGINT   );
        thread_t::ignore_signal( SIGQUIT  );
        thread_t::ignore_signal( SIGUSR1  );
        thread_t::ignore_signal( SIGUSR2  );
        thread_t::ignore_signal( SIGTERM  );
        thread_t::ignore_signal( SIGCHLD  );
        thread_t::ignore_signal( SIGTTIN  );
        thread_t::ignore_signal( SIGTTOU  );
        thread_t::ignore_signal( SIGWINCH );

        pid_t pid = 0;

        ESYSCALL(
            "forking grandchild process",
            "fork",
            pid = fork(),
            pid >= 0,
            "grandchild process forked " << ( pid == 0 ? "(i am grandchild)" : "(i am child)" )
        );

        if ( pid == 0 ) {
            _grandchild( c_pipe, g_pipe );
            return;         // TODO: or exit?
        }; // if

        g_pipe.writer().close();

        ESYSCALL(
            "anti-zombying grandchild",
            "waitpid",
            error = waitpid( pid, NULL, WNOHANG ),
            error != -1,
            "grandchild anti-zombied"
        );

        // We cannot just close pipe: on the parent end ir will be not clear if everything is ok
        // or child silently died. So let us write `ok' to the pipe -- parent will know that we
        // are really ok.
        c_pipe.writer().write( ok );

    } catch ( std::exception const & ex ) {

        c_pipe.writer().write( string_t( ex.what() ) + "\n" );

    } catch ( ... ) {

        c_pipe.writer().write( "Unknown exception occurred\n" );

    }; // try

    c_pipe.writer().close();

}; // _child