pike.git / src / modules / _Stdio / socket.c

version» Context lines:

pike.git/src/modules/_Stdio/socket.c:56:   #include <sys/protosw.h>   #endif      #ifdef HAVE_SYS_SOCKETVAR_H   #include <sys/socketvar.h>   #endif      #ifdef HAVE_SYS_UN_H   #include <sys/un.h>   #endif -  +    #include "dmalloc.h"      /*! @module Stdio    */      /*! @class Port    */      struct port   {
pike.git/src/modules/_Stdio/socket.c:190:    *! @seealso    *! @[bind], @[accept]    */   static void port_listen_fd(INT32 args)   {    struct port *p = THIS;    struct svalue *cb = NULL;    int fd;    do_close(p);    -  get_all_args("Port->listen_fd", args, "%d.%*", &fd, &cb); +  get_all_args("listen_fd", args, "%d.%*", &fd, &cb);       if(fd<0)    {    errno = p->my_errno=EBADF;    pop_n_elems(args);    push_int(0);    return;    }       if(fd_listen(fd, 16384) < 0)
pike.git/src/modules/_Stdio/socket.c:216:    }       change_fd_for_box (&p->box, fd);    if(cb) assign_accept_cb (p, cb);    p->my_errno=0;    pop_n_elems(args);    push_int(1);   }      /*! @decl int bind(int|string port, void|function accept_callback, @ -  *! void|string ip) +  *! void|string ip, void|string reuse_port)    *!    *! Opens a socket and binds it to port number on the local machine.    *! If the second argument is present, the socket is set to    *! nonblocking and the callback funcition is called whenever    *! something connects to it. The callback will receive the id for    *! this port as argument and should typically call @[accept] to    *! establish a connection.    *!    *! If the optional argument @[ip] is given, @[bind] will try to bind    *! to an interface with that host name or IP number. Omitting this    *! will bind to all available IPv4 addresses; specifying "::" will    *! bind to all IPv4 and IPv6 addresses.    *! -  +  *! If the OS supports TCP_FASTOPEN it is enabled automatically. +  *! +  *! If the OS supports SO_REUSEPORT it is enabled if the fourth argument is true. +  *!    *! @returns    *! 1 is returned on success, zero on failure. @[errno] provides    *! further details about the error in the latter case.    *!    *! @seealso    *! @[accept], @[set_id]    */   static void port_bind(INT32 args)   {    struct port *p = THIS;    PIKE_SOCKADDR addr;    int addr_len,fd,tmp;       do_close(p);       if(args < 1) -  SIMPLE_TOO_FEW_ARGS_ERROR("Port->bind", 1); +  SIMPLE_TOO_FEW_ARGS_ERROR("bind", 1);       if(TYPEOF(Pike_sp[-args]) != PIKE_T_INT &&    (TYPEOF(Pike_sp[-args]) != PIKE_T_STRING ||    Pike_sp[-args].u.string->size_shift)) -  SIMPLE_BAD_ARG_ERROR("Port->bind", 1, "int|string (8bit)"); +  SIMPLE_BAD_ARG_ERROR("bind", 1, "int|string(8bit)");    -  addr_len = get_inet_addr(&addr, (args > 2 && TYPEOF(Pike_sp[2-args])==PIKE_T_STRING? +  addr_len = get_inet_addr(&addr, +  (args > 2 && TYPEOF(Pike_sp[2-args])==PIKE_T_STRING?    Pike_sp[2-args].u.string->str : NULL),    (TYPEOF(Pike_sp[-args]) == PIKE_T_STRING?    Pike_sp[-args].u.string->str : NULL),    (TYPEOF(Pike_sp[-args]) == PIKE_T_INT?    Pike_sp[-args].u.integer : -1), 0);    INVALIDATE_CURRENT_TIME();       fd=fd_socket(SOCKADDR_FAMILY(addr), SOCK_STREAM, 0);       if(fd < 0)    {    p->my_errno=errno;    pop_n_elems(args);    push_int(0);    return;    } -  + #ifdef SO_REUSEPORT +  if( args > 3 && Pike_sp[3-args].u.integer ) +  { +  int o=1; +  if(fd_setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *)&o, sizeof(int)) < 0) +  { +  p->my_errno=errno; +  while (fd_close(fd) && errno == EINTR) {} +  errno = p->my_errno; +  pop_n_elems(args); +  push_int(0); +  return; +  } +  } + #endif   #ifndef __NT__    {    int o=1;    if(fd_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&o, sizeof(int)) < 0)    {    p->my_errno=errno;    while (fd_close(fd) && errno == EINTR) {}    errno = p->my_errno;    pop_n_elems(args);    push_int(0);
pike.git/src/modules/_Stdio/socket.c:300: Inside #if defined(IPV6_V6ONLY) && defined(IPPROTO_IPV6)
   * cf http://msdn.microsoft.com/en-us/library/windows/desktop/bb513665(v=vs.85).aspx    */    int o = 0;    fd_setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&o, sizeof(int));    }   #endif       my_set_close_on_exec(fd,1);       THREADS_ALLOW_UID(); -  tmp=fd_bind(fd, (struct sockaddr *)&addr, addr_len) < 0 || fd_listen(fd, 16384) < 0; +  if( !(tmp=fd_bind(fd, (struct sockaddr *)&addr, addr_len) < 0) ) + #ifdef TCP_FASTOPEN +  tmp = 256, +  setsockopt(fd,SOL_TCP, TCP_FASTOPEN, &tmp, sizeof(tmp)), + #endif +  (tmp = fd_listen(fd, 16384) < 0);    THREADS_DISALLOW_UID();       if(!Pike_fp->current_object->prog)    {    if (fd >= 0)    while (fd_close(fd) && errno == EINTR) {}    Pike_error("Object destructed in Stdio.Port->bind()\n");    }       if(tmp)
pike.git/src/modules/_Stdio/socket.c:364: Inside #if defined(HAVE_SYS_UN_H)
  static void bind_unix(INT32 args)   {    struct port *p = THIS;    struct sockaddr_un *addr;    struct pike_string *path;    struct svalue *cb = NULL;    int addr_len,fd,tmp;       do_close(p);    -  get_all_args("Port->bind_unix", args, "%n.%*", &path, &cb); +  get_all_args("bind_unix", args, "%n.%*", &path, &cb);       /* NOTE: Some operating systems (eg Linux 2.6) do not support    * paths longer than what fits into a plain struct sockaddr_un.    */    addr_len = sizeof(struct sockaddr_un) + path->len + 1 -    sizeof(addr->sun_path);    addr = xalloc(addr_len);       strcpy(addr->sun_path, path->str);    addr->sun_family = AF_UNIX;
pike.git/src/modules/_Stdio/socket.c:482:    (TYPEOF(Pike_sp[-args]) == PIKE_T_STRING &&    (Pike_sp[-args].u.string->len != 5 ||    strcmp("stdin",Pike_sp[-args].u.string->str))))    {    port_bind(args); /* pops stack */    return;    }else{    struct port *p = THIS;       if(TYPEOF(Pike_sp[-args]) != PIKE_T_STRING) -  SIMPLE_TOO_FEW_ARGS_ERROR("Port->create", 1); +  SIMPLE_TOO_FEW_ARGS_ERROR("create", 1);       /* FIXME: Check that the argument is "stdin". */       do_close(p);    change_fd_for_box (&p->box, 0);       if(fd_listen(p->box.fd, 16384) < 0)    {    p->my_errno=errno;    }else{
pike.git/src/modules/_Stdio/socket.c:659:    *!    *! @seealso    *! @[query_backend]    */   static void port_set_backend (INT32 args)   {    struct port *p = THIS;    struct Backend_struct *backend;       if (!args) -  SIMPLE_TOO_FEW_ARGS_ERROR ("Stdio.Port->set_backend", 1); +  SIMPLE_TOO_FEW_ARGS_ERROR ("set_backend", 1);    if (TYPEOF(Pike_sp[-args]) != PIKE_T_OBJECT) -  SIMPLE_BAD_ARG_ERROR ("Stdio.Port->set_backend", 1, "object(Pike.Backend)"); +  SIMPLE_BAD_ARG_ERROR ("set_backend", 1, "object(Pike.Backend)");    backend = get_storage (Pike_sp[-args].u.object, Backend_program);    if (!backend) -  SIMPLE_BAD_ARG_ERROR ("Stdio.Port->set_backend", 1, "object(Pike.Backend)"); +  SIMPLE_BAD_ARG_ERROR ("set_backend", 1, "object(Pike.Backend)");       if (p->box.backend)    change_backend_for_box (&p->box, backend);    else    INIT_FD_CALLBACK_BOX (&p->box, backend, p->box.ref_obj,    p->box.fd, 0, got_port_event, 0);       pop_n_elems (args - 1);   }   
pike.git/src/modules/_Stdio/socket.c:704:    /* map_variable takes care of id and accept_callback. */   }      static void exit_port_struct(struct object *UNUSED(o))   {    do_close(THIS);    unhook_fd_callback_box (&THIS->box);    /* map_variable takes care of id and accept_callback. */   }    + int fd_from_portobject( struct object *p ) + { +  struct port *po = get_storage( p, port_program ); +  if(!po) return -1; +  return po->box.fd; + } +  + static void port_query_fd(INT32 UNUSED(args)) + { +  push_int(fd_from_portobject(Pike_fp->current_object)); + }   /*! @endclass    */      /*! @endmodule    */      PMOD_EXPORT struct program *port_program = NULL;      void exit_stdio_port(void)   {
pike.git/src/modules/_Stdio/socket.c:728:   {    ptrdiff_t offset;    START_NEW_PROGRAM_ID (STDIO_PORT);    offset = ADD_STORAGE(struct port);    MAP_VARIABLE("_accept_callback", tMix, 0,    offset + OFFSETOF(port, accept_callback), PIKE_T_MIXED);    MAP_VARIABLE("_id", tMix, 0,    offset + OFFSETOF(port, id), PIKE_T_MIXED);    /* function(int|string,void|mixed,void|string:int) */    ADD_FUNCTION("bind", port_bind, -  tFunc(tOr(tInt,tStr) tOr(tVoid,tMix) tOr(tVoid,tStr),tInt), 0); +  tFunc(tOr(tInt,tStr) tOr(tVoid,tMix) tOr(tVoid,tStr) tOr(tVoid,tInt),tInt), 0);   #ifdef HAVE_SYS_UN_H    /* function(int|string,void|mixed,void|string:int) */    ADD_FUNCTION("bind_unix", bind_unix,    tFunc(tStr tOr(tVoid,tMix),tInt), 0);   #endif /* HAVE_SYS_UN_H */    ADD_FUNCTION("close",port_close,tFunc(tNone,tVoid),0);    /* function(int,void|mixed:int) */    ADD_FUNCTION("listen_fd",port_listen_fd,tFunc(tInt tOr(tVoid,tMix),tInt),0);    /* function(mixed:mixed) */    ADD_FUNCTION("set_id",port_set_id,tFunc(tMix,tMix),0);
pike.git/src/modules/_Stdio/socket.c:756:    port_fd_factory_fun_num =    ADD_FUNCTION("fd_factory", port_fd_factory, tFunc(tNone,tObjIs_STDIO_FD),    ID_STATIC);    ADD_FUNCTION("accept",port_accept,tFunc(tNone,tObjIs_STDIO_FD),0);    /* function(void|string|int,void|mixed,void|string:void) */    ADD_FUNCTION("create", port_create,    tFunc(tOr3(tVoid,tStr,tInt) tOr(tVoid,tMix) tOr(tVoid,tStr),    tVoid), 0);    ADD_FUNCTION ("set_backend", port_set_backend, tFunc(tObj,tVoid), 0);    ADD_FUNCTION ("query_backend", port_query_backend, tFunc(tVoid,tObj), 0); +  ADD_FUNCTION ("query_fd", port_query_fd, tFunc(tVoid,tInt), 0);    -  + #ifdef SO_REUSEPORT +  ADD_INT_CONSTANT( "SO_REUSEPORT_SUPPORT", SO_REUSEPORT, 0 ); + #endif + #ifdef TCP_FASTOPEN +  ADD_INT_CONSTANT( "TCP_FASTOPEN_SUPPORT", TCP_FASTOPEN, 0 ); + #endif    set_init_callback(init_port_struct);    set_exit_callback(exit_port_struct);       port_program = end_program();    add_program_constant( "_port", port_program, 0 ); - } +     - int fd_from_portobject( struct object *p ) - { -  struct port *po = get_storage( p, port_program ); -  if(!po) return -1; -  return po->box.fd; +    } -  +