diff --git a/src/encode.c b/src/encode.c index 72fd2e0f7a3b36d1f6633d0e63a4699d21a27709..99cb9b4c6056ae641f07b30fb8b962976f1ade11 100644 --- a/src/encode.c +++ b/src/encode.c @@ -466,41 +466,6 @@ static void encode_type(struct pike_type *t, struct encode_data *data) } } -static void zap_unfinished_program(struct program *p) -{ - int e; - debug_malloc_touch(p); - if(p->flags & PROGRAM_FIXED) return; /* allow natural zapping */ - debug_malloc_touch(p); - if(p->parent) - { - free_program(p->parent); - p->parent=0; - } - for(e=0;e<p->num_constants;e++) - { - free_svalue(& p->constants[e].sval); - mark_free_svalue (&p->constants[e].sval); - } - - for(e=0;e<p->num_inherits;e++) - { - if(p->inherits[e].parent) - { - free_object(p->inherits[e].parent); - p->inherits[e].parent=0; - } - if(e) - { - if(p->inherits[e].prog) - { - free_program(p->inherits[e].prog); - p->inherits[e].prog=0; - } - } - } -} - /* force_encode == 0: Maybe dump the thing later, and only a forward * reference here (applies to programs only). * @@ -2054,7 +2019,7 @@ static int my_extract_char(struct decode_data *data) static DECLSPEC(noreturn) void decode_error ( struct decode_data *data, struct svalue *decoding, const char *msg, ...) - ATTRIBUTE((noreturn)); + ATTRIBUTE((noinline,noreturn)); static DECLSPEC(noreturn) void decode_error ( struct decode_data *data, struct svalue *decoding, const char *msg, ...) @@ -2065,8 +2030,7 @@ static DECLSPEC(noreturn) void decode_error ( struct object *o = fast_clone_object (decode_error_program); struct decode_error_struct *dec = (struct decode_error_struct *) (o->storage + decode_error_offset); - struct generic_error_struct *gen = - (struct generic_error_struct *) get_storage (o, generic_error_program); + struct generic_error_struct *gen = get_storage (o, generic_error_program); ASSERT_THREAD_SWAPPED_IN(); @@ -2450,8 +2414,6 @@ static void zap_placeholder(struct object *placeholder) free_object(placeholder); } -static int init_placeholder(struct object *placeholder); - #define SETUP_DECODE_MEMOBJ(TYPE, U, VAR, ALLOCATE,SCOUR) do { \ struct svalue *tmpptr; \ @@ -4164,27 +4126,6 @@ decode_done:; #endif } -/* Placed after to prevent inlining */ -static int init_placeholder(struct object *placeholder) -{ - JMP_BUF rec; - /* Initialize the placeholder. */ - if(SETJMP(rec)) - { - dmalloc_touch_svalue(&throw_value); - call_handle_error(); - zap_placeholder(placeholder); - UNSETJMP(rec); - return 1; - }else{ - call_pike_initializers(placeholder,0); - UNSETJMP(rec); - return 0; - } -} - - - static struct decode_data *current_decode = NULL; static void free_decode_data (struct decode_data *data, int delay, diff --git a/src/modules/_Stdio/#udp.c# b/src/modules/_Stdio/#udp.c# deleted file mode 100644 index 2c7c9a18774037a7c3ca4343adb63415f61be814..0000000000000000000000000000000000000000 --- a/src/modules/_Stdio/#udp.c# +++ /dev/null @@ -1,1543 +0,0 @@ -/* -|| 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. -*/ - -#define NO_PIKE_SHORTHAND -#include "global.h" - -#include "file_machine.h" - -#include "fdlib.h" -#include "pike_netlib.h" -#include "interpret.h" -#include "svalue.h" -#include "stralloc.h" -#include "array.h" -#include "mapping.h" -#include "object.h" -#include "backend.h" -#include "time_stuff.h" -#include "fd_control.h" - -#include "pike_error.h" -#include "signal_handler.h" -#include "pike_types.h" -#include "threads.h" -#include "bignum.h" - -#include "module_support.h" -#include "builtin_functions.h" -#include "file.h" - -#ifdef HAVE_SYS_TYPE_H -#include <sys/types.h> -#endif - -#include <sys/stat.h> -#ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> -#endif -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#ifdef HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif - -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif /* HAVE_SYS_TIME_H */ - -#ifdef HAVE_POLL - -#ifdef HAVE_POLL_H -#include <poll.h> -#endif /* HAVE_POLL_H */ - -#ifdef HAVE_SYS_POLL_H -#include <sys/poll.h> -#endif /* HAVE_SYS_POLL_H */ - -/* Some constants... */ - -#ifndef POLLRDNORM -#define POLLRDNORM POLLIN -#endif /* !POLLRDNORM */ - -#ifndef POLLRDBAND -#define POLLRDBAND POLLPRI -#endif /* !POLLRDBAND */ - -#else /* !HAVE_POLL */ - -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif - -#endif /* HAVE_POLL */ - -#if ! defined(EWOULDBLOCK) && defined(WSAEWOULDBLOCK) -#define EWOULDBLOCK WSAEWOULDBLOCK -#endif -#if ! defined(EADDRINUSE) && defined(WSAEADDRINUSE) -#define EADDRINUSE WSAEADDRINUSE -#endif - - -#ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif - -#ifdef HAVE_ARPA_INET_H -#ifndef ARPA_INET_H -#include <arpa/inet.h> -#define ARPA_INET_H - -/* Stupid patch to avoid trouble with Linux includes... */ -#ifdef LITTLE_ENDIAN -#undef LITTLE_ENDIAN -#endif - -#endif -#endif - -#ifdef HAVE_SYS_PROTOSW_H -#include <sys/protosw.h> -#endif - -#ifdef HAVE_SYS_STREAM_H -#include <sys/stream.h> -#endif - -#ifdef HAVE_SYS_SOCKETVAR_H -#include <sys/socketvar.h> -#endif - -/* Fix warning on OSF/1 - * - * NOERROR is defined by both sys/stream.h (-1), and arpa/nameser.h (0), - * the latter is included by netdb.h. - */ -#ifdef NOERROR -#undef NOERROR -#endif /* NOERROR */ - -#ifdef HAVE_NETDB_H -#include <netdb.h> -#endif - -#include "dmalloc.h" - -struct udp_storage { - struct fd_callback_box box; /* Must be first. */ - int my_errno; - - int inet_flags; - - int type; - int protocol; - - struct svalue read_callback; /* Mapped. */ -}; - -void zero_udp(struct object *ignored); -int low_exit_udp(void); -void exit_udp(struct object *UNUSED(ignored)) { - low_exit_udp(); -} - -#undef THIS -#define THIS ((struct udp_storage *)Pike_fp->current_storage) -#define THISOBJ (Pike_fp->current_object) -#define FD (THIS->box.fd) - -/*! @module Stdio - */ - -/*! @class UDP - */ - -/*! @decl int(0..1) close() - *! - *! Closes an open UDP port. - *! - *! @note - *! This method was introduced in Pike 7.5. - */ -static void udp_close(INT32 args) -{ - int ret = low_exit_udp(); - zero_udp(NULL); - pop_n_elems(args); - push_int( ret==0 ); -} - -/*! @decl UDP bind(int|string port, string|void address,@ - *!string|int(0..1) no_reuseaddr) - *! - *! Binds a port for receiving or transmitting UDP. - *! - *! @param no_reuseaddr - *! If set to @expr{1@}, Pike will not set the @expr{SO_REUSEADDR@} option - *! on the UDP port. - *! - *! @note - *! @expr{SO_REUSEADDR@} is never applied when binding a random port - *! (@expr{bind(0)@}). - *! - *! In general, @expr{SO_REUSEADDR@} is not desirable on UDP ports. - *! Unless used for receiving multicast, be sure to never bind a - *! non-random port without setting @expr{no_reuseaddr@} to @expr{1@}. - *! - *! @throws - *! Throws error when unable to bind port. - */ -static void udp_bind(INT32 args) -{ - PIKE_SOCKADDR addr; - int addr_len; - int o; - int fd,tmp; -#if !defined(SOL_IP) && defined(HAVE_GETPROTOBYNAME) - static int ip_proto_num = -1; -#endif /* !SOL_IP && HAVE_GETPROTOBYNAME */ - - if(args < 1) - SIMPLE_TOO_FEW_ARGS_ERROR("Stdio.UDP->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("Stdio.UDP->bind", 1, "int|string (8bit)"); - - if(args > 2 && TYPEOF(Pike_sp[2-args]) != PIKE_T_INT) - SIMPLE_BAD_ARG_ERROR("Stdio.UDP->bind", 3, "int(0..1)"); - -#if 0 - f_backtrace(0); - APPLY_MASTER("handle_error", 1); - pop_stack(); -#endif /* 0 */ - - if(FD != -1) - { - fd = FD; - change_fd_for_box (&THIS->box, -1); - fd_close(fd); - } - - THIS->inet_flags &= ~PIKE_INET_FLAG_IPV6; - - addr_len = get_inet_addr(&addr, (args > 1 && TYPEOF(Pike_sp[1-args])==PIKE_T_STRING? - Pike_sp[1-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), - THIS->inet_flags); - INVALIDATE_CURRENT_TIME(); - -#ifdef AF_INET6 - if (SOCKADDR_FAMILY(addr) == AF_INET6) { - THIS->inet_flags |= PIKE_INET_FLAG_IPV6; - } -#endif - - fd = fd_socket(SOCKADDR_FAMILY(addr), THIS->type, THIS->protocol); - if(fd < 0) - { - pop_n_elems(args); - THIS->my_errno=errno; - Pike_error("Stdio.UDP->bind: failed to create socket (%d, %d, %d)\n", - SOCKADDR_FAMILY(addr), THIS->type, THIS->protocol); - } - - /* Make sure this fd gets closed on exec. */ - set_close_on_exec(fd, 1); - - o=1; - /* linux kernel commit f24d43c07e208372aa3d3bff419afbf43ba87698 introduces - * a behaviour change where you can get used random ports if bound with - * SO_REUSEADDR. */ - if(addr.ipv4.sin_port && (args > 2 ? !Pike_sp[2-args].u.integer : 1) - && fd_setsockopt(fd, SOL_SOCKET,SO_REUSEADDR, - (char *)&o, sizeof(int)) < 0) - { - fd_close(fd); - THIS->my_errno=errno; - Pike_error("Stdio.UDP->bind: setsockopt SO_REUSEADDR failed\n"); - } - -#if defined(IPV6_V6ONLY) && defined(IPPROTO_IPV6) - 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 - */ - o = 0; - fd_setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&o, sizeof(int)); - } -#endif - -#ifndef SOL_IP -#ifdef HAVE_GETPROTOBYNAME - if (ip_proto_num == -1) { - /* NOTE: getprotobyname(3N) is not MT-safe. */ - struct protoent *proto = getprotobyname("ip"); - if (!proto) { - /* No entry for IP, assume zero. */ - ip_proto_num = 0; - } else { - ip_proto_num = proto->p_proto; - } - } -#define SOL_IP ip_proto_num -#else /* !HAVE_GETPROTOBYNAME */ -#define SOL_IP 0 -#endif /* HAVE_GETPROTOBYNAME */ -#endif /* SOL_IP */ - -#ifdef IP_HDRINCL - /* From mtr-0.28:net.c: FreeBSD wants this to avoid sending - out packets with protocol type RAW to the network. */ - - if (THIS->type==SOCK_RAW && THIS->protocol==255 /* raw */) - if(fd_setsockopt(fd, SOL_IP, IP_HDRINCL, (char *)&o, sizeof(int))) - Pike_error("Stdio.UDP->bind: setsockopt IP_HDRINCL failed\n"); -#endif /* IP_HDRINCL */ - - THREADS_ALLOW_UID(); - - tmp=fd_bind(fd, (struct sockaddr *)&addr, addr_len)<0; - - THREADS_DISALLOW_UID(); - - if(tmp) - { - fd_close(fd); - THIS->my_errno=errno; - Pike_error("Stdio.UDP->bind: failed to bind to port %d\n", - (unsigned INT16)Pike_sp[-args].u.integer); - return; - } - - if(!Pike_fp->current_object->prog) - { - if (fd >= 0) - while (fd_close(fd) && errno == EINTR) {} - Pike_error("Object destructed in Stdio.UDP->bind()\n"); - } - - change_fd_for_box (&THIS->box, fd); - pop_n_elems(args); - ref_push_object(THISOBJ); -} - - -/*! @decl UDP set_fd(int fd) - *! - *! Use the file descriptor @[fd] for UDP. - *! @seealso - *! @[bind] - */ -static void udp_set_fd(INT32 args) -{ - int fd; - - get_all_args("set_fd", args, "%d", &fd); - - if(FD != -1) - { - int curfd = FD; - change_fd_for_box (&THIS->box, -1); - fd_close(curfd); - } - - change_fd_for_box (&THIS->box, fd); - pop_n_elems(args); - ref_push_object(THISOBJ); -} - -/*! @decl int query_fd() - *! - *! Gets the file descriptor for this UDP port. - */ -static void udp_query_fd(INT32 args) -{ - pop_n_elems(args); - push_int(FD); -} - - - -/*! @decl int(0..1) enable_broadcast() - *! - *! Set the broadcast flag. - *! If enabled then sockets receive packets sent to a broadcast - *! address and they are allowed to send packets to a - *! broadcast address. - *! - *! @returns - *! Returns @expr{1@} on success, @expr{0@} (zero) otherwise. - *! - *! @note - *! This is normally only avalable to root users. - */ -void udp_enable_broadcast(INT32 args) -{ -#ifdef SO_BROADCAST - int o = 1; - pop_n_elems(args); - push_int(fd_setsockopt(FD, SOL_SOCKET, SO_BROADCAST, (char *)&o, sizeof(int))); - THIS->my_errno=errno; -#else /* SO_BROADCAST */ - pop_n_elems(args); - push_int(0); -#endif /* SO_BROADCAST */ -} - -/*! @decl int(0..1) enable_multicast(string reply_address) - *! Set the local device for a multicast socket. - *! - *! @param reply_address - *! Local address that should appear in the multicast packets. - *! - *! See also the Unix man page for setsocketopt IPPROTO_IP IP_MULTICAST_IF - *! and IPPROTO_IPV6 IPV6_MULTICAST_IF. - *! - *! @note - *! This function did not support IPv6 in Pike 7.8. - */ -void udp_enable_multicast(INT32 args) -{ - int result; - char *ip; - PIKE_SOCKADDR reply; - - get_all_args("enable_multicast", args, "%s", &ip); - - get_inet_addr(&reply, ip, NULL, -1, THIS->inet_flags); - INVALIDATE_CURRENT_TIME(); - -#ifdef AF_INET6 - if (THIS->inet_flags & PIKE_INET_FLAG_IPV6) { - if(SOCKADDR_FAMILY(reply) != AF_INET6) - Pike_error("Multicast only supported for IPv6.\n"); - - result = fd_setsockopt(FD, IPPROTO_IPV6, IPV6_MULTICAST_IF, - (char *)&reply.ipv6.sin6_addr, - sizeof(reply.ipv6.sin6_addr)); - pop_n_elems(args); - push_int(result); - return; - } -#endif - if(SOCKADDR_FAMILY(reply) != AF_INET) - Pike_error("Multicast only supported for IPv4.\n"); - - result = fd_setsockopt(FD, IPPROTO_IP, IP_MULTICAST_IF, - (char *)&reply.ipv4.sin_addr, - sizeof(reply.ipv4.sin_addr)); - pop_n_elems(args); - push_int(result); -} - -/*! @decl int set_multicast_ttl(int ttl) - *! Set the time-to-live value of outgoing multicast packets - *! for this socket. - *! - *! @param ttl - *! The number of router hops sent multicast packets should - *! survive. - *! - *! It is very important for multicast packets to set the - *! smallest TTL possible. The default before calling this - *! function is 1 which means that multicast packets don't - *! leak from the local network unless the user program - *! explicitly requests it. - *! - *! See also the Unix man page for setsocketopt IPPROTO_IP IP_MULTICAST_TTL - *! and IPPROTO_IPV6 IPV6_MULTICAST_HOPS. - *! - *! @note - *! This function did not support IPv6 in Pike 7.8 and earlier. - *! - *! @seealso - *! @[add_membership()] - */ -void udp_set_multicast_ttl(INT32 args) -{ - int ttl; - get_all_args("set_multicast_ttl", args, "%d", &ttl); - pop_n_elems(args); -#ifdef AF_INET6 - if (THIS->inet_flags & PIKE_INET_FLAG_IPV6) { - push_int( fd_setsockopt(FD, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, - (char *)&ttl, sizeof(int)) ); - return; - } -#endif - push_int( fd_setsockopt(FD, IPPROTO_IP, IP_MULTICAST_TTL, - (char *)&ttl, sizeof(int)) ); -} - -/*! @decl int add_membership(string group, void|string address) - *! Join a multicast group. - *! - *! @param group - *! @[group] contains the address of the multicast group the - *! application wants to join. It must be a valid multicast address. - *! - *! @param address - *! @[address] is the address of the local interface with which - *! the system should join to the multicast group. If not provided - *! the system will select an appropriate interface. - *! - *! See also the Unix man page for setsocketopt IPPROTO_IP IP_ADD_MEMBERSHIP - *! and IPPROTO_IPV6 IPV6_JOIN_GROUP. - *! - *! @note - *! The @[address] parameter is currently not supported for IPv6. - *! - *! @note - *! This function did not support IPv6 in Pike 7.8 and earlier. - *! - *! @seealso - *! @[drop_membership()] - */ -void udp_add_membership(INT32 args) -{ - int face=0; - char *group; - char *address=0; - struct ip_mreq sock; - PIKE_SOCKADDR addr; - - get_all_args("add_membership", args, "%s.%s%d", &group, &address, &face); - - get_inet_addr(&addr, group, NULL, -1, THIS->inet_flags); - INVALIDATE_CURRENT_TIME(); - -#ifdef AF_INET6 - if (THIS->inet_flags & PIKE_INET_FLAG_IPV6) { - struct ipv6_mreq sock; - - if (address) - Pike_error("Interface address is not supported for IPv6.\n"); - - /* NB: This sets imr_interface to IN6ADDR_ANY, - * and clears imr_ifindex if it exists. - */ - MEMSET(&sock, 0, sizeof(sock)); - - if(SOCKADDR_FAMILY(addr) != AF_INET6) - Pike_error("Mixing IPv6 and other multicast is not supported.\n"); - - sock.ipv6mr_multiaddr = addr.ipv6.sin6_addr; - - pop_n_elems(args); - push_int( fd_setsockopt(FD, IPPROTO_IPV6, IPV6_JOIN_GROUP, - (char *)&sock, sizeof(sock)) ); - return; - } -#endif /* AF_INET6 */ - - /* NB: This sets imr_interface to INADDR_ANY, - * and clears imr_ifindex if it exists. - */ - MEMSET(&sock, 0, sizeof(sock)); - - if(SOCKADDR_FAMILY(addr) != AF_INET) - Pike_error("Mixing IPv6 and IPv4 multicast is not supported.\n"); - - sock.imr_multiaddr = addr.ipv4.sin_addr; - - if (address) { - get_inet_addr(&addr, address, NULL, -1, THIS->inet_flags); - INVALIDATE_CURRENT_TIME(); - - if(SOCKADDR_FAMILY(addr) != AF_INET) - Pike_error("Mixing IPv6 and IPv4 multicast is not supported.\n"); - - sock.imr_interface = addr.ipv4.sin_addr; - } - - pop_n_elems(args); - push_int( fd_setsockopt(FD, IPPROTO_IP, IP_ADD_MEMBERSHIP, - (char *)&sock, sizeof(sock)) ); -} - -/*! @decl int drop_membership(string group, void|string address) - *! Leave a multicast group. - *! - *! @param group - *! @[group] contains the address of the multicast group the - *! application wants to join. It must be a valid multicast address. - *! - *! @param address - *! @[address] is the address of the local interface with which - *! the system should join to the multicast group. If not provided - *! the system will select an appropriate interface. - *! - *! See also the Unix man page for setsocketopt IPPROTO_IP IP_DROP_MEMBERSHIP - *! and IPPROTO_IPV6 IPV6_LEAVE_GROUP. - *! - *! @note - *! The @[address] parameter is currently not supported for IPv6. - *! - *! @note - *! This function did not support IPv6 in Pike 7.8 and earlier. - *! - *! @seealso - *! @[add_membership()] - */ -void udp_drop_membership(INT32 args) -{ - int face=0; - char *group; - char *address=0; - struct ip_mreq sock; - PIKE_SOCKADDR addr; - - get_all_args("drop_membership", args, "%s.%s%d", &group, &address, &face); - - get_inet_addr(&addr, group, NULL, -1, THIS->inet_flags); - INVALIDATE_CURRENT_TIME(); - -#ifdef AF_INET6 - if (THIS->inet_flags & PIKE_INET_FLAG_IPV6) { - struct ipv6_mreq sock; - - if (address) - Pike_error("Interface address is not supported for IPv6.\n"); - - /* NB: This sets imr_interface to IN6ADDR_ANY, - * and clears imr_ifindex if it exists. - */ - MEMSET(&sock, 0, sizeof(sock)); - - if(SOCKADDR_FAMILY(addr) != AF_INET6) - Pike_error("Mixing IPv6 and other multicast is not supported.\n"); - - sock.ipv6mr_multiaddr = addr.ipv6.sin6_addr; - - pop_n_elems(args); - push_int( fd_setsockopt(FD, IPPROTO_IPV6, IPV6_LEAVE_GROUP, - (char *)&sock, sizeof(sock)) ); - return; - } -#endif /* AF_INET6 */ - - /* NB: This sets imr_interface to INADDR_ANY, - * and clears imr_ifindex if it exists. - */ - MEMSET(&sock, 0, sizeof(sock)); - - if(SOCKADDR_FAMILY(addr) != AF_INET) - Pike_error("Mixing IPv6 and IPv4 multicast is not supported.\n"); - - sock.imr_multiaddr = addr.ipv4.sin_addr; - - if (address) { - get_inet_addr(&addr, address, NULL, -1, THIS->inet_flags); - INVALIDATE_CURRENT_TIME(); - - if(SOCKADDR_FAMILY(addr) != AF_INET) - Pike_error("Mixing IPv6 and IPv4 multicast is not supported.\n"); - - sock.imr_interface = addr.ipv4.sin_addr; - } - - pop_n_elems(args); - push_int( fd_setsockopt(FD, IPPROTO_IP, IP_DROP_MEMBERSHIP, - (char *)&sock, sizeof(sock)) ); -} - -/*! @decl int(0..1) wait(int|float timeout) - *! - *! Check for data and wait max. @[timeout] seconds. - *! - *! @returns - *! Returns @expr{1@} if data are ready, @expr{0@} (zero) otherwise. - */ -void udp_wait(INT32 args) -{ -#ifdef HAVE_POLL - struct pollfd pollfds[1]; - int ms; -#else /* !HAVE_POLL */ - fd_set rset; - struct timeval tv; -#endif /* HAVE_POLL */ - FLOAT_TYPE timeout; - int fd = FD; - int res; - int e; - - get_all_args("wait", args, "%F", &timeout); - - if (timeout < 0.0) { - timeout = 0.0; - } - - if (fd < 0) { - Pike_error("udp->wait(): Port not bound!\n"); - } - -#ifdef HAVE_POLL - THREADS_ALLOW(); - - pollfds->fd = fd; - pollfds->events = POLLIN; - pollfds->revents = 0; - ms = timeout * 1000; - - do { - res = poll(pollfds, 1, ms); - e = errno; - } while (res < 0 && e == EINTR) - - THREADS_DISALLOW(); - if (!res) { - /* Timeout */ - } else if (res < 0) { - /* Error */ - Pike_error("udp->wait(): poll() failed with errno %d\n", e); - } else { - /* Success? */ - if (pollfds->revents) { - res = 1; - } else { - res = 0; - } - } -#else /* !HAVE_POLL */ - THREADS_ALLOW(); - - FD_ZERO(&rset); - FD_SET(fd, &rset); - tv.tv_sec = DO_NOT_WARN((int)timeout); - tv.tv_usec = DO_NOT_WARN((int)((timeout - ((int)timeout)) * 1000000.0)); - res = fd_select(fd+1, &rset, NULL, NULL, &tv); - e = errno; - - THREADS_DISALLOW(); - if (!res) { - /* Timeout */ - } else if (res < 0) { - /* Error */ - Pike_error("udp->wait(): select() failed with errno %d\n", e); - } else { - /* Success? */ - if (FD_ISSET(fd, &rset)) { - res = 1; - } else { - res = 0; - } - } -#endif /* HAVE_POLL */ - - pop_n_elems(args); - - push_int(res); -} - -/* NOTE: Some versions of AIX seem to have a - * #define events reqevents - * in one of the poll headerfiles. This will break - * the fd_box event handling. - */ -#undef events - -#define UDP_BUFFSIZE 65536 - -/*! @decl mapping(string:int|string) read() - *! @decl mapping(string:int|string) read(int flag) - *! - *! Read from the UDP socket. - *! - *! Flag @[flag] is a bitfield, 1 for out of band data and 2 for peek - *! - *! @returns - *! mapping(string:int|string) in the form - *! ([ - *! "data" : string received data - *! "ip" : string received from this ip - *! "port" : int ...and this port - *! ]) - *! - *! @seealso - *! @[set_read_callback()], @[MSG_OOB], @[MSG_PEEK] - */ -void udp_read(INT32 args) -{ - int flags = 0, res=0, fd, e; - PIKE_SOCKADDR from; - char buffer[UDP_BUFFSIZE]; - ACCEPT_SIZE_T fromlen = sizeof(from); - - if(args) - { - if(Pike_sp[-args].u.integer & 1) { - flags |= MSG_OOB; - } - if(Pike_sp[-args].u.integer & 2) { -#ifdef MSG_PEEK - flags |= MSG_PEEK; -#else /* !MSG_PEEK */ - /* FIXME: What should we do here? */ -#endif /* MSG_PEEK */ - } - if(Pike_sp[-args].u.integer & ~3) { - Pike_error("Illegal 'flags' value passed to udp->read([int flags])\n"); - } - } - pop_n_elems(args); - fd = FD; - if (FD < 0) - Pike_error("Stdio.UDP->read: not open\n"); - do { - THREADS_ALLOW(); - res = fd_recvfrom(fd, buffer, UDP_BUFFSIZE, flags, - (struct sockaddr *)&from, &fromlen); - e = errno; - THREADS_DISALLOW(); - - check_threads_etc(); - } while((res==-1) && (e==EINTR)); - - THIS->my_errno=errno=e; - - if(res<0) - { - switch(e) - { -#ifdef WSAEBADF - case WSAEBADF: -#endif - case EBADF: - if (THIS->box.backend) - set_fd_callback_events (&THIS->box, 0, 0); - Pike_error("Socket closed\n"); -#ifdef ESTALE - case ESTALE: -#endif - case EIO: - if (THIS->box.backend) - set_fd_callback_events (&THIS->box, 0, 0); - Pike_error("I/O error\n"); - case ENOMEM: -#ifdef ENOSR - case ENOSR: -#endif /* ENOSR */ - Pike_error("Out of memory\n"); -#ifdef ENOTSOCK - case ENOTSOCK: - Pike_fatal("reading from non-socket fd!!!\n"); -#endif - case EINVAL: - if (!(flags & MSG_OOB)) { - Pike_error("Socket read failed with EINVAL.\n"); - } - /* FALL_THROUGH */ - case EWOULDBLOCK: - push_int( 0 ); - return; - - default: - Pike_error("Socket read failed with errno %d.\n", e); - } - } - /* Now comes the interresting part. - * make a nice mapping from this stuff.. - */ - push_text("data"); - push_string( make_shared_binary_string(buffer, res) ); - - push_text("ip"); -#ifdef fd_inet_ntop - if (!fd_inet_ntop( SOCKADDR_FAMILY(from), SOCKADDR_IN_ADDR(from), - buffer, sizeof(buffer) )) { - push_text("UNSUPPORTED"); - } else { - /* NOTE: IPv6-mapped IPv4 addresses may only - * connect to other IPv4 addresses. - * - * Make the Pike-level code believe it has an actual IPv4 address - * when getting a mapped address (::FFFF:a.b.c.d). - */ - if ((!strncmp(buffer, "::FFFF:", 7) || !strncmp(buffer, "::ffff:", 7)) && - !strchr(buffer + 7, ':')) { - push_text(buffer+7); - } else { - push_text(buffer); - } - } -#else - push_text( inet_ntoa( *SOCKADDR_IN_ADDR(from) ) ); -#endif - - push_text("port"); - push_int(ntohs(from.ipv4.sin_port)); - f_aggregate_mapping( 6 ); - - if (!(THIS->inet_flags & PIKE_INET_FLAG_NB)) - INVALIDATE_CURRENT_TIME(); -} - -/*! @decl int send(string to, int|string port, string message) - *! @decl int send(string to, int|string port, string message, int flags) - *! - *! Send data to a UDP socket. The recipient address will be @[to] - *! and port will be @[port]. - *! - *! Flag @[flag] is a bitfield, 1 for out of band data and - *! 2 for don't route flag. - *! - *! @returns - *! The number of bytes that were actually written. - */ -void udp_sendto(INT32 args) -{ - int flags = 0, fd, e; - ptrdiff_t res = 0; - PIKE_SOCKADDR to; - int to_len; - char *str; - ptrdiff_t len; - - if(FD < 0) - Pike_error("UDP: not open\n"); - - check_all_args("send", args, - BIT_STRING, BIT_INT|BIT_STRING, BIT_STRING, BIT_INT|BIT_VOID, 0); - - if(args>3) - { - if(Pike_sp[3-args].u.integer & 1) { - flags |= MSG_OOB; - } - if(Pike_sp[3-args].u.integer & 2) { -#ifdef MSG_DONTROUTE - flags |= MSG_DONTROUTE; -#else /* !MSG_DONTROUTE */ - /* FIXME: What should we do here? */ -#endif /* MSG_DONTROUTE */ - } - if(Pike_sp[3-args].u.integer & ~3) { - Pike_error("Illegal 'flags' value passed to " - "Stdio.UDP->send(string to, int|string port, string message, int flags)\n"); - } - } - - to_len = get_inet_addr(&to, Pike_sp[-args].u.string->str, - (TYPEOF(Pike_sp[1-args]) == PIKE_T_STRING? - Pike_sp[1-args].u.string->str : NULL), - (TYPEOF(Pike_sp[1-args]) == PIKE_T_INT? - Pike_sp[1-args].u.integer : -1), - THIS->inet_flags); - INVALIDATE_CURRENT_TIME(); - - fd = FD; - str = Pike_sp[2-args].u.string->str; - len = Pike_sp[2-args].u.string->len; - - do { - THREADS_ALLOW(); - res = fd_sendto( fd, str, len, flags, (struct sockaddr *)&to, to_len); - e = errno; - THREADS_DISALLOW(); - - check_threads_etc(); - } while((res == -1) && e==EINTR); - - if(res<0) - { - switch(e) - { -#ifdef EMSGSIZE - case EMSGSIZE: -#endif - Pike_error("Too big message\n"); - case EBADF: - if (THIS->box.backend) - set_fd_callback_events (&THIS->box, 0, 0); - Pike_error("Socket closed\n"); - case ENOMEM: -#ifdef ENOSR - case ENOSR: -#endif /* ENOSR */ - Pike_error("Out of memory\n"); - case EINVAL: -#ifdef ENOTSOCK - case ENOTSOCK: - if (THIS->box.backend) - set_fd_callback_events (&THIS->box, 0, 0); - Pike_error("Not a socket!!!\n"); -#endif - case EWOULDBLOCK: - Pike_error("Message would block.\n"); - } - } - pop_n_elems(args); - push_int64(res); - if (!(THIS->inet_flags & PIKE_INET_FLAG_NB)) - INVALIDATE_CURRENT_TIME(); -} - - -static int got_udp_event (struct fd_callback_box *box, int DEBUGUSED(event)) -{ - struct udp_storage *u = (struct udp_storage *) box; -#ifdef PIKE_DEBUG - if (event != PIKE_FD_READ) - Pike_fatal ("Got unexpected event %d.\n", event); -#endif - - u->my_errno = errno; /* Propagate backend setting. */ - - check_destructed (&u->read_callback); - if (UNSAFE_IS_ZERO (&u->read_callback)) - set_fd_callback_events (&u->box, 0, 0); - else { - apply_svalue (&u->read_callback, 0); - if (TYPEOF(Pike_sp[-1]) == PIKE_T_INT && Pike_sp[-1].u.integer == -1) { - pop_stack(); - return -1; - } - pop_stack(); - } - return 0; -} - -void zero_udp(struct object *o) -{ - INIT_FD_CALLBACK_BOX(&THIS->box, NULL, o, -1, 0, got_udp_event, 0); - THIS->my_errno = 0; - THIS->inet_flags = PIKE_INET_FLAG_UDP; - THIS->type=SOCK_DGRAM; - THIS->protocol=0; - /* map_variable handles read_callback. */ -} - -int low_exit_udp() -{ - int fd = FD; - int ret = 0; - - unhook_fd_callback_box(&THIS->box); - FD = -1; - - if(fd != -1) - { - THREADS_ALLOW(); - ret = fd_close(fd); - THREADS_DISALLOW(); - } - - /* map_variable handles read_callback. */ - - return ret; -} - -static void udp_set_read_callback(INT32 args) -{ - struct udp_storage *u = THIS; - if(args < 1) - SIMPLE_TOO_FEW_ARGS_ERROR("Stdio.UDP->set_read_callback", 1); - if(args > 1) - pop_n_elems(args-1); - - assign_svalue(& u->read_callback, Pike_sp-1); - if (UNSAFE_IS_ZERO (Pike_sp - 1)) { - if (u->box.backend) - set_fd_callback_events (&u->box, 0, 0); - } - else { - if (!u->box.backend) - INIT_FD_CALLBACK_BOX (&u->box, default_backend, u->box.ref_obj, - u->box.fd, PIKE_BIT_FD_READ, got_udp_event, 0); - else - set_fd_callback_events (&u->box, PIKE_BIT_FD_READ, 0); - } - - pop_stack(); - ref_push_object(THISOBJ); -} - -static void udp_set_nonblocking(INT32 args) -{ - if (FD < 0) Pike_error("File not open.\n"); - - if (args) - { - udp_set_read_callback(args); - pop_stack(); - } - set_nonblocking(FD,1); - THIS->inet_flags |= PIKE_INET_FLAG_NB; - ref_push_object(THISOBJ); -} - -/*! @decl object set_blocking() - *! - *! Sets this object to be blocking. - */ -static void udp_set_blocking(INT32 args) -{ - if (FD < 0) Pike_error("File not open.\n"); - set_nonblocking(FD,0); - THIS->inet_flags &= ~PIKE_INET_FLAG_NB; - pop_n_elems(args); - ref_push_object(THISOBJ); -} - -/*! @decl int(0..1) connect(string address, int|string port) - *! - *! Establish an UDP connection. - *! - *! This function connects an UDP socket previously created with - *! @[Stdio.UDP()] to a remote socket. The @[address] is the IP name or - *! number for the remote machine. - *! - *! @returns - *! Returns @expr{1@} on success, @expr{0@} (zero) otherwise. - *! - *! @note - *! If the socket is in nonblocking mode, you have to wait - *! for a write or close callback before you know if the connection - *! failed or not. - *! - *! @seealso - *! @[bind()], @[query_address()] - */ -static void udp_connect(INT32 args) -{ - PIKE_SOCKADDR addr; - int addr_len; - struct pike_string *dest_addr = NULL; - struct svalue *dest_port = NULL; - - int tmp; - - get_all_args("UDP.connect", args, "%S%*", &dest_addr, &dest_port); - - if(TYPEOF(*dest_port) != PIKE_T_INT && - (TYPEOF(*dest_port) != PIKE_T_STRING || dest_port->u.string->size_shift)) - SIMPLE_BAD_ARG_ERROR("UDP.connect", 2, "int|string (8bit)"); - - addr_len = get_inet_addr(&addr, dest_addr->str, - (TYPEOF(*dest_port) == PIKE_T_STRING? - dest_port->u.string->str : NULL), - (TYPEOF(*dest_port) == PIKE_T_INT? - dest_port->u.integer : -1), - THIS->inet_flags); - INVALIDATE_CURRENT_TIME(); - - if(FD < 0) - { - FD = fd_socket(SOCKADDR_FAMILY(addr), SOCK_DGRAM, 0); - if(FD < 0) - { - THIS->my_errno=errno; - Pike_error("Stdio.UDP->connect: failed to create socket\n"); - } - set_close_on_exec(FD, 1); - -#if defined(IPV6_V6ONLY) && defined(IPPROTO_IPV6) - 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 - } - - tmp=FD; - THREADS_ALLOW(); - tmp=fd_connect(tmp, (struct sockaddr *)&addr, addr_len); - THREADS_DISALLOW(); - - if (!(THIS->inet_flags & PIKE_INET_FLAG_NB)) - INVALIDATE_CURRENT_TIME(); - - if(tmp < 0) - { - THIS->my_errno=errno; - Pike_error("Stdio.UDP->connect: failed to connect\n"); - }else{ - THIS->my_errno=0; - pop_n_elems(args); - push_int(1); - } -} - -/*! @decl string query_address() - *! - *! Returns the local address of a socket on the form "x.x.x.x port". - *! If this file is not a socket, not connected or some other error occurs, - *! zero is returned. - */ -static void udp_query_address(INT32 args) -{ - PIKE_SOCKADDR addr; - int i; - int fd = FD; - char buffer[496]; - ACCEPT_SIZE_T len; - - if(fd <0) - Pike_error("Stdio.UDP->query_address(): Port not bound yet.\n"); - - THREADS_ALLOW(); - - len=sizeof(addr); - i=fd_getsockname(fd,(struct sockaddr *)&addr,&len); - - THREADS_DISALLOW(); - - pop_n_elems(args); - if(i < 0 || len < (int)sizeof(addr.ipv4)) - { - push_int(0); - return; - } - -#ifdef fd_inet_ntop - fd_inet_ntop(SOCKADDR_FAMILY(addr), SOCKADDR_IN_ADDR(addr), - buffer, sizeof(buffer)-20); -#else - q=inet_ntoa(*SOCKADDR_IN_ADDR(addr)); - strncpy(buffer,q,sizeof(buffer)-20); - buffer[sizeof(buffer)-20]=0; -#endif - sprintf(buffer+strlen(buffer)," %d",(int)(ntohs(addr.ipv4.sin_port))); - - /* NOTE: IPv6-mapped IPv4 addresses may only connect to other IPv4 addresses. - * - * Make the Pike-level code believe it has an actual IPv4 address - * when getting a mapped address (::FFFF:a.b.c.d). - */ - if ((!strncmp(buffer, "::FFFF:", 7) || !strncmp(buffer, "::ffff:", 7)) && - !strchr(buffer + 7, ':')) { - push_text(buffer+7); - } else { - push_text(buffer); - } -} - -/*! @decl void set_backend (Pike.Backend backend) - *! - *! Set the backend used for the read callback. - *! - *! @note - *! The backend keeps a reference to this object as long as there can - *! be calls to the read callback, but this object does not keep a - *! reference to the backend. - *! - *! @seealso - *! @[query_backend] - */ -static void udp_set_backend (INT32 args) -{ - struct udp_storage *u = THIS; - struct Backend_struct *backend; - - if (!args) - SIMPLE_TOO_FEW_ARGS_ERROR ("Stdio.UDP->set_backend", 1); - if (TYPEOF(Pike_sp[-args]) != PIKE_T_OBJECT) - SIMPLE_BAD_ARG_ERROR ("Stdio.UDP->set_backend", 1, "object(Pike.Backend)"); - backend = (struct Backend_struct *) - get_storage (Pike_sp[-args].u.object, Backend_program); - if (!backend) - SIMPLE_BAD_ARG_ERROR ("Stdio.UDP->set_backend", 1, "object(Pike.Backend)"); - - if (u->box.backend) - change_backend_for_box (&u->box, backend); - else - INIT_FD_CALLBACK_BOX (&u->box, backend, u->box.ref_obj, - u->box.fd, 0, got_udp_event, 0); - - pop_n_elems (args - 1); -} - -/*! @decl Pike.Backend query_backend() - *! - *! Return the backend used for the read callback. - *! - *! @seealso - *! @[set_backend] - */ -static void udp_query_backend (INT32 args) -{ - pop_n_elems (args); - ref_push_object (get_backend_obj (THIS->box.backend ? THIS->box.backend : - default_backend)); -} - -/*! @decl int errno() - *! - *! Returns the error code for the last command on this object. - *! Error code is normally cleared when a command is successful. - */ -static void udp_errno(INT32 args) -{ - pop_n_elems(args); - push_int(THIS->my_errno); -} - -/*! @decl UDP set_type(int sock_type) - *! @decl UDP set_type(int sock_type, int family) - *! - *! Sets socket type and protocol family. - */ -static void udp_set_type(INT32 args) -{ - int type, proto = 0; - - get_all_args("Stdio.UDP->set_type",args,"%d.%d",&type,&proto); - - THIS->type=type; - THIS->protocol=proto; - - pop_n_elems(args); - ref_push_object(THISOBJ); -} - -/*! @decl array(int) get_type() - *! - *! Returns socket type and protocol family. - */ -static void udp_get_type(INT32 args) -{ - pop_n_elems(args); - push_int(THIS->type); - push_int(THIS->protocol); - f_aggregate(2); -} - -/*! @decl void set_buffer(int bufsize, string mode) - *! @decl void set_buffer(int bufsize) - *! - *! Set internal socket buffer. - *! - *! This function sets the internal buffer size of a socket or stream. - *! - *! The second argument allows you to set the read or write buffer by - *! specifying @expr{"r"@} or @expr{"w"@}. - *! - *! @note - *! It is not guaranteed that this function actually does anything, - *! but it certainly helps to increase data transfer speed when it does. - *! - *! @seealso - *! @[open_socket()], @[accept()] - */ -static void udp_set_buffer(INT32 args) -{ - INT_TYPE bufsize; - int flags = FILE_READ | FILE_WRITE; - char *c = NULL; - - if(FD==-1) - Pike_error("Stdio.UDP->set_buffer() on closed file.\n"); - - get_all_args("Stdio.UDP->set_buffer", args, "%+.%s", &bufsize, &c); - - if(bufsize < 0) - Pike_error("Bufsize must be larger than zero.\n"); - - if(c) - { - flags = 0; - do - { - switch( *c ) - { - case 'w': flags |= FILE_WRITE; break; - case 'r': flags |= FILE_READ; break; - } - } while( *c++ ); - } - pop_n_elems(args); - -#ifdef SOCKET_BUFFER_MAX -#if SOCKET_BUFFER_MAX - if(bufsize>SOCKET_BUFFER_MAX) bufsize=SOCKET_BUFFER_MAX; -#endif -#ifdef SO_RCVBUF - if(flags & FILE_READ) - { - int tmp=bufsize; - fd_setsockopt(FD,SOL_SOCKET, SO_RCVBUF, (char *)&tmp, sizeof(tmp)); - } -#endif /* SO_RCVBUF */ - -#ifdef SO_SNDBUF - if(flags & FILE_WRITE) - { - int tmp=bufsize; - fd_setsockopt(FD,SOL_SOCKET, SO_SNDBUF, (char *)&tmp, sizeof(tmp)); - } -#endif /* SO_SNDBUF */ -#endif -} - -/*! @decl constant MSG_OOB - *! @fixme - *! Document this constant. - */ - -/*! @decl constant MSG_PEEK - *! @fixme - *! Document this constant. - */ - -/*! @endclass - */ - -/*! @endmodule - */ - -void init_stdio_udp(void) -{ - START_NEW_PROGRAM_ID (STDIO_UDP); - - ADD_STORAGE(struct udp_storage); - - PIKE_MAP_VARIABLE("_read_callback", OFFSETOF(udp_storage, read_callback), - tFunc(tNone, tInt_10), PIKE_T_MIXED, ID_PROTECTED|ID_PRIVATE); - - ADD_FUNCTION("set_type",udp_set_type, - tFunc(tInt tOr(tVoid,tInt),tObj),0); - ADD_FUNCTION("get_type",udp_get_type, - tFunc(tNone,tArr(tInt)),0); - - ADD_FUNCTION("close", udp_close, tFunc(tNone, tInt01), 0); - - ADD_FUNCTION("bind",udp_bind, - tFunc(tOr(tInt,tStr) tOr(tVoid,tStr) tOr(tVoid,tInt),tObj),0); - - ADD_FUNCTION("set_fd",udp_set_fd, - tFunc(tInt,tObj),0); - - ADD_FUNCTION("query_fd",udp_query_fd, - tFunc(tInt,tObj),0); - - ADD_FUNCTION("enable_broadcast", udp_enable_broadcast, - tFunc(tNone,tInt01), 0); - - ADD_FUNCTION("enable_multicast", udp_enable_multicast, - tFunc(tStr,tInt01), 0); - - ADD_FUNCTION("set_multicast_ttl", udp_set_multicast_ttl, - tFunc(tInt,tInt), 0); - - ADD_FUNCTION("add_membership", udp_add_membership, - tFunc(tStr tOr(tVoid,tStr tOr(tVoid,tInt)),tInt), 0); - - ADD_FUNCTION("drop_membership", udp_drop_membership, - tFunc(tStr tOr(tVoid,tStr tOr(tVoid,tInt)),tInt), 0); - - ADD_FUNCTION("wait", udp_wait, tFunc(tOr(tInt, tFloat), tInt), 0); - - ADD_FUNCTION("read",udp_read, - tFunc(tOr(tInt,tVoid),tMap(tStr,tOr(tInt,tStr))),0); - - add_integer_constant("MSG_OOB", 1, 0); -#ifdef MSG_PEEK - add_integer_constant("MSG_PEEK", 2, 0); -#endif /* MSG_PEEK */ - - ADD_FUNCTION("send",udp_sendto, - tFunc(tStr tOr(tInt,tStr) tStr tOr(tVoid,tInt),tInt),0); - - ADD_FUNCTION("connect",udp_connect, - tFunc(tString tOr(tInt,tStr),tInt),0); - - ADD_FUNCTION("_set_nonblocking", udp_set_nonblocking, - tFunc(tOr(tFunc(tVoid,tVoid),tVoid),tObj), 0 ); - ADD_FUNCTION("_set_read_callback", udp_set_read_callback, - tFunc(tFunc(tVoid,tVoid),tObj), 0 ); - - ADD_FUNCTION("set_blocking",udp_set_blocking,tFunc(tVoid,tObj), 0 ); - ADD_FUNCTION("query_address",udp_query_address,tFunc(tNone,tStr),0); - - ADD_FUNCTION ("set_backend", udp_set_backend, tFunc(tObj,tVoid), 0); - ADD_FUNCTION ("query_backend", udp_query_backend, tFunc(tVoid,tObj), 0); - - ADD_FUNCTION("errno",udp_errno,tFunc(tNone,tInt),0); - - ADD_FUNCTION("set_buffer", udp_set_buffer, tFunc(tInt tOr(tStr,tVoid),tVoid), 0); - - set_init_callback(zero_udp); - set_exit_callback(exit_udp); - - end_class("UDP",0); - - START_NEW_PROGRAM_ID (STDIO_SOCK); -#ifdef SOCK_STREAM - add_integer_constant("STREAM",SOCK_STREAM,0); -#endif -#ifdef SOCK_DGRAM - add_integer_constant("DGRAM",SOCK_DGRAM,0); -#endif -#ifdef SOCK_SEQPACKET - add_integer_constant("SEQPACKET",SOCK_SEQPACKET,0); -#endif -#ifdef SOCK_RAW - add_integer_constant("RAW",SOCK_RAW,0); -#endif -#ifdef SOCK_RDM - add_integer_constant("RDM",SOCK_RDM,0); -#endif -#ifdef SOCK_PACKET - add_integer_constant("PACKET",SOCK_PACKET,0); -#endif - push_program(end_program()); - f_call_function(1); - simple_add_constant("SOCK",Pike_sp-1,0); - pop_stack(); - - START_NEW_PROGRAM_ID (STDIO_IPPROTO); - add_integer_constant("IP",0,0); /* Dummy protocol for TCP. */ - add_integer_constant("HOPOPTS",0,0); /* IPv6 Hop-by-Hop options. */ - add_integer_constant("ICMP",1,0); /* Internet Control Message Protocol. */ - add_integer_constant("IGMP",2,0); /* Internet Group Management Protocol. */ - add_integer_constant("GGP", 3, 0); /* Gateway-Gateway Protocol. */ - add_integer_constant("IPIP",4,0); /* IPIP tunnels (older KA9Q tunnels use 94). */ - add_integer_constant("TCP",6,0); /* Transmission Control Protocol. */ - add_integer_constant("EGP",8,0); /* Exterior Gateway Protocol. */ - add_integer_constant("PUP",12,0); /* PUP protocol. */ - add_integer_constant("UDP",17,0); /* User Datagram Protocol. */ - add_integer_constant("IDP",22,0); /* XNS IDP protocol. */ - add_integer_constant("RDP", 27, 0); /* "Reliable Datagram" Protocol. */ - add_integer_constant("TP",29,0); /* SO Transport Protocol Class 4. */ - add_integer_constant("IPV6",41,0); /* IPv6 header. */ - add_integer_constant("ROUTING",43,0); /* IPv6 routing header. */ - add_integer_constant("FRAGMENT",44,0);/* IPv6 fragmentation header. */ - add_integer_constant("RSVP",46,0); /* Reservation Protocol. */ - add_integer_constant("GRE",47,0); /* General Routing Encapsulation. */ - add_integer_constant("ESP",50,0); /* encapsulating security payload. */ - add_integer_constant("AH",51,0); /* authentication header. */ - add_integer_constant("ICMPV6",58,0); /* ICMPv6. */ - add_integer_constant("NONE",59,0); /* IPv6 no next header. */ - add_integer_constant("DSTOPTS",60,0); /* IPv6 destination options. */ - add_integer_constant("MTP",92,0); /* Multicast Transport Protocol. */ - add_integer_constant("ENCAP",98,0); /* Encapsulation Header. */ - add_integer_constant("PIM",103,0); /* Protocol Independent Multicast. */ - add_integer_constant("COMP",108,0); /* Compression Header Protocol. */ - add_integer_constant("RAW",255,0); /* Raw IP packets. */ - push_program(end_program()); - f_call_function(1); - simple_add_constant("IPPROTO",Pike_sp-1,0); - pop_stack(); -} - -void exit_stdio_udp(void) -{ -}