e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
aedfb12002-10-09Martin Nilsson 
6afca92000-07-29Fredrik Hübinette (Hubbe) #define NO_PIKE_SHORTHAND
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h"
5740881998-01-01Fredrik Hübinette (Hubbe) #include "fdlib.h"
5f1c622003-04-30Henrik Grubbström (Grubba) #include "pike_netlib.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "interpret.h" #include "svalue.h" #include "stralloc.h" #include "array.h" #include "object.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "backend.h" #include "fd_control.h"
07513e1996-10-04Fredrik Hübinette (Hubbe) #include "threads.h"
8524151999-12-14Fredrik Hübinette (Hubbe) #include "program_id.h"
c4d1002004-05-14Martin Nilsson #include "module_support.h"
f010202011-11-16Tobias S. Josefowitz #include "time_stuff.h"
5267b71995-08-09Fredrik Hübinette (Hubbe)  #include "file_machine.h" #include "file.h"
bdfb861997-12-22Fredrik Hübinette (Hubbe) #ifdef HAVE_SYS_PARAM_H
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <sys/param.h>
bdfb861997-12-22Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <errno.h> #include <fcntl.h> #include <signal.h>
bdfb861997-12-22Fredrik Hübinette (Hubbe) #ifdef HAVE_SYS_WAIT_H
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <sys/wait.h>
bdfb861997-12-22Fredrik Hübinette (Hubbe) #endif #ifdef HAVE_SYS_SOCKET_H
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <sys/socket.h>
bdfb861997-12-22Fredrik Hübinette (Hubbe) #endif
5ad6ac1995-09-25Per Hedbor #ifdef HAVE_SYS_STREAM_H #include <sys/stream.h>
2a15e51996-11-25Fredrik Hübinette (Hubbe)  /* Ugly patch for AIX 3.2 */ #ifdef u #undef u #endif
5ad6ac1995-09-25Per Hedbor #endif #ifdef HAVE_SYS_PROTOSW_H #include <sys/protosw.h> #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifdef HAVE_SYS_SOCKETVAR_H #include <sys/socketvar.h> #endif
9058842004-05-13Martin Nilsson #ifdef HAVE_SYS_UN_H #include <sys/un.h> #endif
61e9a01998-01-25Fredrik Hübinette (Hubbe) 
f4b4de2014-10-17Henrik Grubbström (Grubba) #if !defined(SOL_TCP) && defined(IPPROTO_TCP)
adde172014-10-17Henrik Grubbström (Grubba)  /* SOL_TCP isn't defined in Solaris. */ #define SOL_TCP IPPROTO_TCP #endif
66f19d2002-02-14Martin Nilsson /*! @module Stdio */ /*! @class Port */
5267b71995-08-09Fredrik Hübinette (Hubbe) struct port {
10dac82004-04-05Martin Stjernholm  struct fd_callback_box box; /* Must be first. */
07513e1996-10-04Fredrik Hübinette (Hubbe)  int my_errno;
f010202011-11-16Tobias S. Josefowitz  unsigned int immediate_cnt;
10dac82004-04-05Martin Stjernholm  struct svalue accept_callback; /* Mapped. */ struct svalue id; /* Mapped. */
5267b71995-08-09Fredrik Hübinette (Hubbe) };
bdfb861997-12-22Fredrik Hübinette (Hubbe) #undef THIS
206c152000-07-07Henrik Grubbström (Grubba) #define THIS ((struct port *)(Pike_fp->current_storage))
5267b71995-08-09Fredrik Hübinette (Hubbe) 
74dfe82012-12-30Jonas Walldén static int got_port_event (struct fd_callback_box *box, int DEBUGUSED(event))
5267b71995-08-09Fredrik Hübinette (Hubbe) {
10dac82004-04-05Martin Stjernholm  struct port *p = (struct port *) box; #ifdef PIKE_DEBUG #ifndef __NT__ if(!query_nonblocking(p->box.fd)) Pike_fatal("Port is in blocking mode in port accept callback!!!\n"); #endif if (event != PIKE_FD_READ) Pike_fatal ("Got unexpected event %d.\n", event); #endif p->my_errno = errno; /* Propagate backend setting. */
f010202011-11-16Tobias S. Josefowitz  p->immediate_cnt++;
10dac82004-04-05Martin Stjernholm  push_svalue (&p->id); apply_svalue(& p->accept_callback, 1); pop_stack(); return 0; }
0941cf2003-10-15Henrik Grubbström (Grubba) 
10dac82004-04-05Martin Stjernholm static void assign_accept_cb (struct port *p, struct svalue *cb) { assign_svalue(& p->accept_callback, cb); if (UNSAFE_IS_ZERO (cb)) { if (p->box.backend)
ca6bd02012-05-01Bill Welliver  set_fd_callback_events (&p->box, 0, 0);
8f7e132005-02-01Martin Stjernholm  set_nonblocking(p->box.fd,0);
10dac82004-04-05Martin Stjernholm  } else { if (!p->box.backend) INIT_FD_CALLBACK_BOX (&p->box, default_backend, p->box.ref_obj,
ca6bd02012-05-01Bill Welliver  p->box.fd, PIKE_BIT_FD_READ, got_port_event, 0);
10dac82004-04-05Martin Stjernholm  else
ca6bd02012-05-01Bill Welliver  set_fd_callback_events (&p->box, PIKE_BIT_FD_READ, 0);
10dac82004-04-05Martin Stjernholm  set_nonblocking(p->box.fd,1); } } static void do_close(struct port *p) { retry: if(p->box.fd >= 0) { if(fd_close(p->box.fd) < 0)
700dac2002-02-05Martin Stjernholm  if(errno == EINTR) { check_threads_etc();
d3ef711995-11-02Fredrik Hübinette (Hubbe)  goto retry;
700dac2002-02-05Martin Stjernholm  }
10dac82004-04-05Martin Stjernholm  change_fd_for_box (&p->box, -1);
f3c7152001-04-14Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe) }
de411a2002-04-01Martin Nilsson /*! @decl mixed set_id(mixed id)
66f19d2002-02-14Martin Nilsson  *!
de411a2002-04-01Martin Nilsson  *! This function sets the id used for accept_callback by this port. *! The default id is @[this_object()]. *! *! @seealso *! @[query_id]
66f19d2002-02-14Martin Nilsson  */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void port_set_id(INT32 args) {
c4d1002004-05-14Martin Nilsson  check_all_args("Port->set_id", args, BIT_MIXED, 0);
6afca92000-07-29Fredrik Hübinette (Hubbe)  assign_svalue(& THIS->id, Pike_sp-args);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args-1); }
66f19d2002-02-14Martin Nilsson /*! @decl mixed query_id() *!
de411a2002-04-01Martin Nilsson  *! This function returns the id for this port. The id is normally the *! first argument to accept_callback. *! *! @seealso *! @[set_id]
66f19d2002-02-14Martin Nilsson  */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void port_query_id(INT32 args) { pop_n_elems(args);
6afca92000-07-29Fredrik Hübinette (Hubbe)  assign_svalue_no_free(Pike_sp++,& THIS->id);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
66f19d2002-02-14Martin Nilsson /*! @decl int errno() *!
8f7e132005-02-01Martin Stjernholm  *! If the last call done on this port failed, this function will *! return an integer describing what went wrong. Refer to your unix *! manual for further information.
66f19d2002-02-14Martin Nilsson  */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void port_errno(INT32 args) { pop_n_elems(args);
07513e1996-10-04Fredrik Hübinette (Hubbe)  push_int(THIS->my_errno);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
de411a2002-04-01Martin Nilsson /*! @decl int listen_fd(int fd, void|function accept_callback) *!
8f7e132005-02-01Martin Stjernholm  *! This function does the same as @[bind], except that instead of *! creating a new socket and bind it to a port, it expects the file *! descriptor @[fd] to be an already open port.
66f19d2002-02-14Martin Nilsson  *!
de411a2002-04-01Martin Nilsson  *! @note *! This function is only for the advanced user, and is generally used *! when sockets are passed to Pike at exec time. *! *! @seealso *! @[bind], @[accept]
66f19d2002-02-14Martin Nilsson  */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void port_listen_fd(INT32 args) {
10dac82004-04-05Martin Stjernholm  struct port *p = THIS;
ddc1a32010-07-27Martin Stjernholm  struct svalue *cb = NULL;
5267b71995-08-09Fredrik Hübinette (Hubbe)  int fd;
10dac82004-04-05Martin Stjernholm  do_close(p);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
69c0aa2014-08-25Martin Nilsson  get_all_args("listen_fd", args, "%d.%*", &fd, &cb);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
b80e8b2000-05-20Per Hedbor  if(fd<0)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
10dac82004-04-05Martin Stjernholm  errno = p->my_errno=EBADF;
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(0); return; }
5740881998-01-01Fredrik Hübinette (Hubbe)  if(fd_listen(fd, 16384) < 0)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
10dac82004-04-05Martin Stjernholm  p->my_errno=errno;
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(0); return; }
10dac82004-04-05Martin Stjernholm  change_fd_for_box (&p->box, fd);
ddc1a32010-07-27Martin Stjernholm  if(cb) assign_accept_cb (p, cb);
10dac82004-04-05Martin Stjernholm  p->my_errno=0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(1); }
c4d1002004-05-14Martin Nilsson /*! @decl int bind(int|string port, void|function accept_callback, @
5727112014-09-02Per Hedbor  *! void|string ip, void|string reuse_port)
de411a2002-04-01Martin Nilsson  *!
8f7e132005-02-01Martin Stjernholm  *! 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
64ce982012-05-30Chris Angelico  *! 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.
8f7e132005-02-01Martin Stjernholm  *!
86eae42014-08-26Per Hedbor  *! If the OS supports TCP_FASTOPEN it is enabled automatically. *!
5727112014-09-02Per Hedbor  *! If the OS supports SO_REUSEPORT it is enabled if the fourth argument is true. *!
8f7e132005-02-01Martin Stjernholm  *! @returns *! 1 is returned on success, zero on failure. @[errno] provides *! further details about the error in the latter case.
66f19d2002-02-14Martin Nilsson  *!
de411a2002-04-01Martin Nilsson  *! @seealso
8f7e132005-02-01Martin Stjernholm  *! @[accept], @[set_id]
66f19d2002-02-14Martin Nilsson  */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void port_bind(INT32 args) {
10dac82004-04-05Martin Stjernholm  struct port *p = THIS;
cf77092003-04-24Marcus Comstedt  PIKE_SOCKADDR addr;
486dbe2003-04-23Marcus Comstedt  int addr_len,fd,tmp;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
10dac82004-04-05Martin Stjernholm  do_close(p);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(args < 1)
de22f72014-08-25Martin Nilsson  SIMPLE_TOO_FEW_ARGS_ERROR("bind", 1);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_INT && (TYPEOF(Pike_sp[-args]) != PIKE_T_STRING ||
3c0d582003-04-22Marcus Comstedt  Pike_sp[-args].u.string->size_shift))
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("bind", 1, "int|string(8bit)");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
5727112014-09-02Per Hedbor  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),
017b572011-10-28Henrik Grubbström (Grubba)  (TYPEOF(Pike_sp[-args]) == PIKE_T_INT?
20c99e2003-04-24Marcus Comstedt  Pike_sp[-args].u.integer : -1), 0);
f010202011-11-16Tobias S. Josefowitz  INVALIDATE_CURRENT_TIME();
20c99e2003-04-24Marcus Comstedt  fd=fd_socket(SOCKADDR_FAMILY(addr), SOCK_STREAM, 0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(fd < 0) {
10dac82004-04-05Martin Stjernholm  p->my_errno=errno;
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(0); return; }
5727112014-09-02Per Hedbor #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
1b21b81998-01-21Fredrik Hübinette (Hubbe) #ifndef __NT__
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
e8527f2001-09-24Henrik Grubbström (Grubba)  int o=1; if(fd_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&o, sizeof(int)) < 0) {
10dac82004-04-05Martin Stjernholm  p->my_errno=errno;
d6964c2003-09-30Martin Stjernholm  while (fd_close(fd) && errno == EINTR) {}
10dac82004-04-05Martin Stjernholm  errno = p->my_errno;
8e8ff82003-01-05Martin Nilsson  pop_n_elems(args);
e8527f2001-09-24Henrik Grubbström (Grubba)  push_int(0); return; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
1b21b81998-01-21Fredrik Hübinette (Hubbe) #endif
cb22561995-10-11Fredrik Hübinette (Hubbe) 
2266322012-01-31Henrik Grubbström (Grubba) #if defined(IPV6_V6ONLY) && defined(IPPROTO_IPV6)
3020732012-01-30Henrik Grubbström (Grubba)  if (SOCKADDR_FAMILY(addr) == AF_INET6) { /* Attempt to enable dual-stack (ie mapped IPv4 adresses). * Needed on WIN32. * 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
fd36c61997-01-29Fredrik Hübinette (Hubbe)  my_set_close_on_exec(fd,1);
cb22561995-10-11Fredrik Hübinette (Hubbe) 
ef1e931998-03-26Henrik Grubbström (Grubba)  THREADS_ALLOW_UID();
86eae42014-08-26Per Hedbor  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);
ef1e931998-03-26Henrik Grubbström (Grubba)  THREADS_DISALLOW_UID();
07513e1996-10-04Fredrik Hübinette (Hubbe) 
cedaa42007-11-03Henrik Grubbström (Grubba)  if(!Pike_fp->current_object->prog) { if (fd >= 0) while (fd_close(fd) && errno == EINTR) {} Pike_error("Object destructed in Stdio.Port->bind()\n"); }
07513e1996-10-04Fredrik Hübinette (Hubbe)  if(tmp)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
10dac82004-04-05Martin Stjernholm  p->my_errno=errno;
d6964c2003-09-30Martin Stjernholm  while (fd_close(fd) && errno == EINTR) {}
10dac82004-04-05Martin Stjernholm  errno = p->my_errno;
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(0); return; }
10dac82004-04-05Martin Stjernholm  change_fd_for_box (&p->box, fd); if(args > 1) assign_accept_cb (p, Pike_sp+1-args); p->my_errno=0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(1); }
6eb3362004-05-13H. William Welliver III  #ifdef HAVE_SYS_UN_H
07324b2004-05-13H. William Welliver III /*! @decl int bind_unix(string path, void|function accept_callback)
6eb3362004-05-13H. William Welliver III  *!
8f7e132005-02-01Martin Stjernholm  *! Opens a Unix domain socket at the given path in the file system. *! 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.
6eb3362004-05-13H. William Welliver III  *! *! @returns
8f7e132005-02-01Martin Stjernholm  *! 1 is returned on success, zero on failure. @[errno] provides *! further details about the error in the latter case.
6eb3362004-05-13H. William Welliver III  *! *! @note
8f7e132005-02-01Martin Stjernholm  *! This function is only available on systems that support Unix domain
6eb3362004-05-13H. William Welliver III  *! sockets. *!
200c102009-07-23Henrik Grubbström (Grubba)  *! @note *! @[path] had a quite restrictive length limit (~100 characters) *! prior to Pike 7.8.334. *!
6eb3362004-05-13H. William Welliver III  *! @seealso
8f7e132005-02-01Martin Stjernholm  *! @[accept], @[set_id]
6eb3362004-05-13H. William Welliver III  */
b817822009-12-07Henrik Grubbström (Grubba) static void bind_unix(INT32 args)
6eb3362004-05-13H. William Welliver III { struct port *p = THIS;
200c102009-07-23Henrik Grubbström (Grubba)  struct sockaddr_un *addr;
c4d1002004-05-14Martin Nilsson  struct pike_string *path;
b817822009-12-07Henrik Grubbström (Grubba)  struct svalue *cb = NULL;
6eb3362004-05-13H. William Welliver III  int addr_len,fd,tmp; do_close(p);
69c0aa2014-08-25Martin Nilsson  get_all_args("bind_unix", args, "%n.%*", &path, &cb);
6eb3362004-05-13H. William Welliver III 
1f0b462010-02-24Henrik Grubbström (Grubba)  /* 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);
200c102009-07-23Henrik Grubbström (Grubba)  addr = xalloc(addr_len);
6eb3362004-05-13H. William Welliver III 
200c102009-07-23Henrik Grubbström (Grubba)  strcpy(addr->sun_path, path->str); addr->sun_family = AF_UNIX;
9670672009-07-23Henrik Grubbström (Grubba) #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN /* Length including NUL. */
caa2e42009-07-23Henrik Grubbström (Grubba)  addr->sun_len = path->len + 1;
9670672009-07-23Henrik Grubbström (Grubba) #endif
6eb3362004-05-13H. William Welliver III  fd=fd_socket(AF_UNIX, SOCK_STREAM, 0); if(fd < 0) {
200c102009-07-23Henrik Grubbström (Grubba)  free(addr);
6eb3362004-05-13H. William Welliver III  p->my_errno=errno; pop_n_elems(args); push_int(0); return; } #ifndef __NT__ { int o=1;
b817822009-12-07Henrik Grubbström (Grubba)  do { tmp = fd_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&o, sizeof(int));
5344ae2012-12-02Peter Bortas  } while ((tmp < 0) && (errno == EINTR));
6eb3362004-05-13H. William Welliver III  } #endif my_set_close_on_exec(fd,1); THREADS_ALLOW_UID();
200c102009-07-23Henrik Grubbström (Grubba)  do {
b817822009-12-07Henrik Grubbström (Grubba)  tmp = fd_bind(fd, (struct sockaddr *)addr, addr_len);
200c102009-07-23Henrik Grubbström (Grubba)  } while ((tmp < 0) && (errno == EINTR)); if (tmp >= 0) { do { tmp = fd_listen(fd, 16384); } while ((tmp < 0) && (errno == EINTR)); }
6eb3362004-05-13H. William Welliver III  THREADS_DISALLOW_UID();
200c102009-07-23Henrik Grubbström (Grubba)  free(addr);
cedaa42007-11-03Henrik Grubbström (Grubba)  if(!Pike_fp->current_object->prog) { if (fd >= 0) while (fd_close(fd) && errno == EINTR) {}
b817822009-12-07Henrik Grubbström (Grubba)  Pike_error("Object destructed in Stdio.Port->bind_unix()\n");
cedaa42007-11-03Henrik Grubbström (Grubba)  }
200c102009-07-23Henrik Grubbström (Grubba)  if(tmp < 0)
6eb3362004-05-13H. William Welliver III  { p->my_errno=errno; while (fd_close(fd) && errno == EINTR) {} errno = p->my_errno; pop_n_elems(args); push_int(0); return; } change_fd_for_box (&p->box, fd);
ddc1a32010-07-27Martin Stjernholm  if (cb) assign_accept_cb (p, cb);
6eb3362004-05-13H. William Welliver III  p->my_errno=0; pop_n_elems(args); push_int(1); } #endif /* HAVE_SYS_UN_H */
2ea6c02004-04-04Martin Stjernholm /*! @decl void close() *! *! Closes the socket. */
96f63c2015-11-25Henrik Grubbström (Grubba) static void port_close (INT32 UNUSED(args))
2ea6c02004-04-04Martin Stjernholm {
10dac82004-04-05Martin Stjernholm  do_close (THIS);
2ea6c02004-04-04Martin Stjernholm }
8f7e132005-02-01Martin Stjernholm /*! @decl void create(int|string port, void|function accept_callback, @ *! void|string ip) *! @decl void create("stdin", void|function accept_callback) *! *! When called with an int or any string except @expr{"stdin"@} as *! first argument, this function does the same as @[bind()] would do *! with the same arguments. *! *! When called with @expr{"stdin"@} as argument, a socket is created *! out of the file descriptor 0. This is only useful if that actually *! IS a socket to begin with. *! *! @seealso *! @[bind], @[listen_fd]
de411a2002-04-01Martin Nilsson  */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void port_create(INT32 args) { if(args) {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) == PIKE_T_INT || (TYPEOF(Pike_sp[-args]) == PIKE_T_STRING &&
8f7e132005-02-01Martin Stjernholm  (Pike_sp[-args].u.string->len != 5 || strcmp("stdin",Pike_sp[-args].u.string->str))))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
ed7b192015-11-16Martin Nilsson  port_bind(args);
e4556f1997-04-10Marcus Comstedt  return;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{
10dac82004-04-05Martin Stjernholm  struct port *p = THIS;
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_STRING)
de22f72014-08-25Martin Nilsson  SIMPLE_TOO_FEW_ARGS_ERROR("create", 1);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
cedaa42007-11-03Henrik Grubbström (Grubba)  /* FIXME: Check that the argument is "stdin". */
10dac82004-04-05Martin Stjernholm  do_close(p); change_fd_for_box (&p->box, 0);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
10dac82004-04-05Martin Stjernholm  if(fd_listen(p->box.fd, 16384) < 0)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
10dac82004-04-05Martin Stjernholm  p->my_errno=errno;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{
10dac82004-04-05Martin Stjernholm  if(args > 1) assign_accept_cb (p, Pike_sp+1-args);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } } } } extern struct program *file_program;
fe061b2009-02-23Henrik Grubbström (Grubba) static int port_fd_factory_fun_num = -1; static void port_fd_factory(INT32 args) { pop_n_elems(args); push_object(clone_object(file_program, 0)); }
d849ab2003-10-30Martin Stjernholm /*! @decl Stdio.File accept()
8f7e132005-02-01Martin Stjernholm  *! *! Get the first connection request waiting for this port and return *! it as a connected socket. *! *! If no connection request is waiting and the port is in nonblocking *! mode (i.e. an accept callback is installed) then zero is returned. *! Otherwise this function waits until a connection has arrived.
ee7ba02008-06-13Henrik Grubbström (Grubba)  *!
fe061b2009-02-23Henrik Grubbström (Grubba)  *! In Pike 7.8 and later the returned object is created via @[fd_factory()]. *!
ee7ba02008-06-13Henrik Grubbström (Grubba)  *! @note *! In Pike 7.7 and later the resulting file object will be assigned *! to the same backend as the port object.
8e8ff82003-01-05Martin Nilsson  */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void port_accept(INT32 args) {
cf77092003-04-24Marcus Comstedt  PIKE_SOCKADDR addr;
07513e1996-10-04Fredrik Hübinette (Hubbe)  struct port *this=THIS;
d6964c2003-09-30Martin Stjernholm  int fd, err;
7c6a531998-08-07Henrik Grubbström (Grubba)  ACCEPT_SIZE_T len=0;
cedaa42007-11-03Henrik Grubbström (Grubba)  int one = 1;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
10dac82004-04-05Martin Stjernholm  if(this->box.fd < 0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("port->accept(): Port not open.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
bac0ab2005-01-19Henrik Grubbström (Grubba)  /* FIXME: Race. */ THIS->box.revents = 0;
07513e1996-10-04Fredrik Hübinette (Hubbe)  THREADS_ALLOW();
a1ad681998-01-16Fredrik Hübinette (Hubbe)  len=sizeof(addr);
d6964c2003-09-30Martin Stjernholm  do {
10dac82004-04-05Martin Stjernholm  fd=fd_accept(this->box.fd, (struct sockaddr *)&addr, &len);
d6964c2003-09-30Martin Stjernholm  err = errno; } while (fd < 0 && err == EINTR);
07513e1996-10-04Fredrik Hübinette (Hubbe)  THREADS_DISALLOW();
f010202011-11-16Tobias S. Josefowitz  INVALIDATE_CURRENT_TIME();
cb22561995-10-11Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(fd < 0) {
10dac82004-04-05Martin Stjernholm  this->my_errno=errno = err;
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(0); return; }
6283791995-09-01Fredrik Hübinette (Hubbe) 
cedaa42007-11-03Henrik Grubbström (Grubba)  /* We don't really care if setsockopt fails, since it's just a hint. */ while ((fd_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(int)) < 0) && (errno == EINTR)) one = 1;
fd36c61997-01-29Fredrik Hübinette (Hubbe)  my_set_close_on_exec(fd,1);
1227c42009-02-23Henrik Grubbström (Grubba)  push_new_fd_object(port_fd_factory_fun_num, fd, FILE_READ | FILE_WRITE, SOCKET_CAPABILITIES);
ee71702000-01-30Per Hedbor 
ee7ba02008-06-13Henrik Grubbström (Grubba)  if (this->box.backend) {
1227c42009-02-23Henrik Grubbström (Grubba)  struct object *o = Pike_sp[-1].u.object; struct my_file *f = (struct my_file *)
017b572011-10-28Henrik Grubbström (Grubba)  (o->storage + o->prog->inherits[SUBTYPEOF(Pike_sp[-1])].storage_offset);
ee7ba02008-06-13Henrik Grubbström (Grubba)  change_backend_for_box(&f->box, this->box.backend); }
1227c42009-02-23Henrik Grubbström (Grubba)  stack_pop_n_elems_keep_top(args);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
5abc862008-05-12Martin Stjernholm /*! @decl string query_address()
66f19d2002-02-14Martin Nilsson  *!
5abc862008-05-12Martin Stjernholm  *! Get the address and port of the local socket end-point. *! *! @returns *! This function returns the address and port of a socket end-point *! on the form @expr{"x.x.x.x port"@} (IPv4) or *! @expr{"x:x:x:x:x:x:x:x port"@} (IPv6). *! *! If there is some error querying or formatting the address, *! @expr{0@} (zero) is returned and @[errno()] will return the *! error code. *! *! @throws *! An error is thrown if the socket isn't bound.
66f19d2002-02-14Martin Nilsson  */
dfa0b61997-01-21Fredrik Hübinette (Hubbe) static void socket_query_address(INT32 args) {
cf77092003-04-24Marcus Comstedt  PIKE_SOCKADDR addr;
eaf8b91998-07-15Fredrik Hübinette (Hubbe)  int i;
dfafa92003-09-01Martin Nilsson  char buffer[496];
7c6a531998-08-07Henrik Grubbström (Grubba)  ACCEPT_SIZE_T len;
dfa0b61997-01-21Fredrik Hübinette (Hubbe) 
10dac82004-04-05Martin Stjernholm  if(THIS->box.fd <0)
5abc862008-05-12Martin Stjernholm  Pike_error("Stdio.Port->query_address(): Socket not bound yet.\n");
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  len=sizeof(addr);
10dac82004-04-05Martin Stjernholm  i=fd_getsockname(THIS->box.fd,(struct sockaddr *)&addr,&len);
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  pop_n_elems(args);
486dbe2003-04-23Marcus Comstedt  if(i < 0 || len < (int)sizeof(addr.ipv4))
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  { THIS->my_errno=errno; push_int(0); return; }
6a539c2009-05-28Henrik Grubbström (Grubba) #ifdef fd_inet_ntop if(!fd_inet_ntop(SOCKADDR_FAMILY(addr), SOCKADDR_IN_ADDR(addr), buffer, sizeof(buffer)-20))
5abc862008-05-12Martin Stjernholm  { THIS->my_errno = errno; push_int(0); return; } #else if(SOCKADDR_FAMILY(addr) == AF_INET) { char *q = inet_ntoa(*SOCKADDR_IN_ADDR(addr)); strncpy(buffer,q,sizeof(buffer)-20); buffer[sizeof(buffer)-20]=0; }else{ #ifdef EAFNOSUPPORT
a76ca12008-05-12Henrik Grubbström (Grubba)  THIS->my_errno = EAFNOSUPPORT;
cae06e2003-04-22Marcus Comstedt #else
a76ca12008-05-12Henrik Grubbström (Grubba)  THIS->my_errno = EINVAL;
5abc862008-05-12Martin Stjernholm #endif push_int(0); return; }
cae06e2003-04-22Marcus Comstedt #endif
486dbe2003-04-23Marcus Comstedt  sprintf(buffer+strlen(buffer)," %d",(int)(ntohs(addr.ipv4.sin_port)));
dfa0b61997-01-21Fredrik Hübinette (Hubbe) 
90e0f72003-12-12Martin Nilsson  push_text(buffer);
dfa0b61997-01-21Fredrik Hübinette (Hubbe) }
10dac82004-04-05Martin Stjernholm /*! @decl void set_backend (Pike.Backend backend) *! *! Set the backend used for the accept callback. *! *! @note *! The backend keeps a reference to this object as long as the port *! is accepting connections, but this object does not keep a *! reference to the backend. *! *! @seealso *! @[query_backend] */ static void port_set_backend (INT32 args) { struct port *p = THIS; struct Backend_struct *backend; if (!args)
de22f72014-08-25Martin Nilsson  SIMPLE_TOO_FEW_ARGS_ERROR ("set_backend", 1);
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-args]) != PIKE_T_OBJECT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR ("set_backend", 1, "object(Pike.Backend)");
13b5ed2014-05-26Per Hedbor  backend = get_storage (Pike_sp[-args].u.object, Backend_program);
10dac82004-04-05Martin Stjernholm  if (!backend)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR ("set_backend", 1, "object(Pike.Backend)");
10dac82004-04-05Martin Stjernholm  if (p->box.backend) change_backend_for_box (&p->box, backend); else INIT_FD_CALLBACK_BOX (&p->box, backend, p->box.ref_obj,
ca6bd02012-05-01Bill Welliver  p->box.fd, 0, got_port_event, 0);
10dac82004-04-05Martin Stjernholm } /*! @decl Pike.Backend query_backend() *! *! Return the backend used for the accept callback. *! *! @seealso *! @[set_backend] */ static void port_query_backend (INT32 args) { pop_n_elems (args); ref_push_object (get_backend_obj (THIS->box.backend ? THIS->box.backend : default_backend)); }
3a56592015-05-18Henrik Grubbström (Grubba) int fd_from_portobject( struct object *p ) { struct port *po = get_storage( p, port_program ); if(!po) return -1; return po->box.fd; } /*! @decl int query_fd() *! *! Returns the file descriptor number associated with this object. */ static void port_query_fd(INT32 UNUSED(args)) { push_int(fd_from_portobject(Pike_fp->current_object)); }
dfa0b61997-01-21Fredrik Hübinette (Hubbe) 
06983f1996-09-22Fredrik Hübinette (Hubbe) static void init_port_struct(struct object *o)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
ca6bd02012-05-01Bill Welliver  INIT_FD_CALLBACK_BOX(&THIS->box, NULL, o, -1, 0, got_port_event, 0);
07513e1996-10-04Fredrik Hübinette (Hubbe)  THIS->my_errno=0;
10dac82004-04-05Martin Stjernholm  /* map_variable takes care of id and accept_callback. */
5267b71995-08-09Fredrik Hübinette (Hubbe) }
74dfe82012-12-30Jonas Walldén static void exit_port_struct(struct object *UNUSED(o))
5267b71995-08-09Fredrik Hübinette (Hubbe) {
10dac82004-04-05Martin Stjernholm  do_close(THIS); unhook_fd_callback_box (&THIS->box); /* map_variable takes care of id and accept_callback. */
5267b71995-08-09Fredrik Hübinette (Hubbe) }
66f19d2002-02-14Martin Nilsson /*! @endclass */ /*! @endmodule */
db1e8d2006-07-05Martin Stjernholm PMOD_EXPORT struct program *port_program = NULL;
ee71702000-01-30Per Hedbor 
29f9a92013-06-11Martin Nilsson void exit_stdio_port(void)
ee71702000-01-30Per Hedbor { free_program( port_program ); }
29f9a92013-06-11Martin Nilsson void init_stdio_port(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
d7ae232000-08-10Henrik Grubbström (Grubba)  ptrdiff_t offset;
48b97a2003-10-28Martin Stjernholm  START_NEW_PROGRAM_ID (STDIO_PORT);
40f3022004-04-11Henrik Grubbström (Grubba)  offset = ADD_STORAGE(struct port);
0032aa2005-01-23Martin Nilsson  MAP_VARIABLE("_accept_callback", tMix, 0,
40f3022004-04-11Henrik Grubbström (Grubba)  offset + OFFSETOF(port, accept_callback), PIKE_T_MIXED);
0032aa2005-01-23Martin Nilsson  MAP_VARIABLE("_id", tMix, 0,
40f3022004-04-11Henrik Grubbström (Grubba)  offset + OFFSETOF(port, id), PIKE_T_MIXED);
3c0d582003-04-22Marcus Comstedt  /* function(int|string,void|mixed,void|string:int) */
40f3022004-04-11Henrik Grubbström (Grubba)  ADD_FUNCTION("bind", port_bind,
fcde912014-09-03Per Hedbor  tFunc(tOr(tInt,tStr) tOr(tVoid,tMix) tOr(tVoid,tStr) tOr(tVoid,tInt),tInt), 0);
6eb3362004-05-13H. William Welliver III #ifdef HAVE_SYS_UN_H /* function(int|string,void|mixed,void|string:int) */
b817822009-12-07Henrik Grubbström (Grubba)  ADD_FUNCTION("bind_unix", bind_unix,
9049992015-04-28Henrik Grubbström (Grubba)  tFunc(tStr tOr(tVoid,tMix),tInt), ID_OPTIONAL);
6eb3362004-05-13H. William Welliver III #endif /* HAVE_SYS_UN_H */
2ea6c02004-04-04Martin Stjernholm  ADD_FUNCTION("close",port_close,tFunc(tNone,tVoid),0);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* 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); /* function(:mixed) */
07228a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("query_id",port_query_id,tFunc(tNone,tMix),0);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(:string) */
07228a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("query_address",socket_query_address,tFunc(tNone,tStr),0);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(:int) */
07228a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("errno",port_errno,tFunc(tNone,tInt),0);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(:object) */
fe061b2009-02-23Henrik Grubbström (Grubba)  port_fd_factory_fun_num = ADD_FUNCTION("fd_factory", port_fd_factory, tFunc(tNone,tObjIs_STDIO_FD), ID_STATIC);
7352a81999-12-14Martin Stjernholm  ADD_FUNCTION("accept",port_accept,tFunc(tNone,tObjIs_STDIO_FD),0);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(void|string|int,void|mixed,void|string:void) */
40f3022004-04-11Henrik Grubbström (Grubba)  ADD_FUNCTION("create", port_create, tFunc(tOr3(tVoid,tStr,tInt) tOr(tVoid,tMix) tOr(tVoid,tStr), tVoid), 0);
10dac82004-04-05Martin Stjernholm  ADD_FUNCTION ("set_backend", port_set_backend, tFunc(tObj,tVoid), 0); ADD_FUNCTION ("query_backend", port_query_backend, tFunc(tVoid,tObj), 0);
4d416e2014-09-04Per Hedbor  ADD_FUNCTION ("query_fd", port_query_fd, tFunc(tVoid,tInt), 0);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
4d416e2014-09-04Per Hedbor #ifdef SO_REUSEPORT
9049992015-04-28Henrik Grubbström (Grubba)  ADD_INT_CONSTANT( "SO_REUSEPORT_SUPPORT", SO_REUSEPORT, ID_OPTIONAL );
4d416e2014-09-04Per Hedbor #endif #ifdef TCP_FASTOPEN
9049992015-04-28Henrik Grubbström (Grubba)  ADD_INT_CONSTANT( "TCP_FASTOPEN_SUPPORT", TCP_FASTOPEN, ID_OPTIONAL );
4d416e2014-09-04Per Hedbor #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  set_init_callback(init_port_struct); set_exit_callback(exit_port_struct);
ee71702000-01-30Per Hedbor  port_program = end_program(); add_program_constant( "_port", port_program, 0 );
5267b71995-08-09Fredrik Hübinette (Hubbe) 
ee71702000-01-30Per Hedbor }