flx_demuxconfig


Start data section to config/demux.fpc[1 /1 ]
     1: Name: demux
     2: Description: Event handling
     3: Version: $Id: flx_demuxconfig.pak,v 1.14 2006/07/21 06:45:40 skaller Exp $
     4: 
     5: provides_dlib: -ldemux_dynamic
     6: provides_slib: -ldemux_static
     7: Requires: flx_pthread
     8: flx_requires_driver: flx_arun
     9: 
End data section to config/demux.fpc[1]
Start python section to spkgs/demux.py[1 /1 ]
     1: #line 31 "./lpsrc/flx_demuxconfig.pak"
     2: 
     3: DEMUXRTL_INTERFACES = [
     4:  'demux/demux_demuxer.hpp',       # portable
     5:  'demux/demux_posix_demuxer.hpp', # posix
     6:  'demux/demux_timer_queue.hpp',   # portable
     7:  'demux/demux_quitter.hpp',       # portable
     8:  'demux/demux_posix_timer_queue.hpp',   # posix
     9:  'demux/demux_pfileio.hpp',       # posix
    10:  'demux/demux_select_demuxer.hpp',# posix
    11:  'demux/demux_iocp_demuxer.hpp',  # win32 (monolithic)
    12:  'demux/demux_overlapped.hpp',    # win32
    13:  'demux/demux_win_timer_queue.hpp',  # win32
    14:  'demux/demux_kqueue_demuxer.hpp',# osx(10.3 onwards)/bsd
    15:  'demux/demux_evtport_demuxer.hpp',# solaris (9 onwards?)
    16:  'demux/demux_epoll_demuxer.hpp',# linux (>= 2.6)
    17:  'demux/demux_sockety.hpp',       # posix
    18:  'demux/demux_self_piper.hpp',    # posix
    19:  'demux/demux_wself_piper.hpp',   # win32
    20:  'demux/demux_ts_select_demuxer.hpp',
    21:  'demux/demux_poll_demuxer.hpp',  # linux, 10.3 (select impl), 10.4 real.
    22:  'demux/demux_ts_poll_demuxer.hpp',  # idem
    23: ]
    24: 
    25: DEMUX_CPPS = [
    26:   "demux/demux_demuxer",
    27:   "demux/demux_quitter",
    28: ]
    29: 
    30: POSIX_DEMUX_CPPS = [
    31:   "demux/demux_posix_demuxer",      # posix
    32:   "demux/demux_select_demuxer",     # posix
    33:   "demux/demux_posix_timer_queue",  # posix
    34:   "demux/demux_sockety",            # posix
    35:   "demux/demux_self_piper",         # posix
    36:   "demux/demux_pfileio",            # posix
    37:   'demux/demux_ts_select_demuxer',  # posix
    38: ]
    39: 
    40: POLL_DEMUX_CPPS = [
    41:    # I've seen poll on linux and osx10.4 systems.
    42:    # conditionally compiled and used.
    43:   'demux/demux_poll_demuxer',       # I've seen this on linux and osx10.4
    44:   'demux/demux_ts_poll_demuxer',    # ditto
    45: ]
    46: 
    47: WINDOWS_DEMUX_CPPS = [
    48:   "demux/demux_iocp_demuxer",       # windows
    49:   "demux/demux_overlapped",         # windows
    50:   "demux/demux_wself_piper",        # windows
    51:   "demux/demux_win_timer_queue",    # windows
    52: ]
    53: 
    54: EXTRA_SYS_LIBS = ""
    55: if WIN32:
    56:   DEMUX_CPPS = DEMUX_CPPS + WINDOWS_DEMUX_CPPS
    57:   if HAVE_MSVC:
    58:     EXTRA_SYS_LIBS = "/DEFAULTLIB:ws2_32 /DEFAULTLIB:mswsock "
    59:   else:
    60:     # mingw
    61:     EXTRA_SYS_LIBS = "-lws2_32 -lmswsock "
    62: 
    63: 
    64: if POSIX:
    65:   DEMUX_CPPS = DEMUX_CPPS + POSIX_DEMUX_CPPS
    66: 
    67: if HAVE_KQUEUE_DEMUXER:
    68:   DEMUX_CPPS = DEMUX_CPPS + [ "demux/demux_kqueue_demuxer" ]
    69: 
    70: if HAVE_POLL:
    71:   DEMUX_CPPS = DEMUX_CPPS + POLL_DEMUX_CPPS
    72: 
    73: if HAVE_EPOLL:
    74:   DEMUX_CPPS = DEMUX_CPPS + [ "demux/demux_epoll_demuxer" ] # Linux 2.6 +
    75: 
    76: if HAVE_EVTPORTS:
    77:   DEMUX_CPPS = DEMUX_CPPS + [ "demux/demux_evtport_demuxer"] # solaris 10
    78: 
    79: if SOLARIS:
    80:   # RF: this might not be necessary anymore.
    81:   EXTRA_SYS_LIBS = "-lsocket -lnsl "
    82: 
    83: cpp_cpps = DEMUX_CPPS
    84: rtl_interfaces = DEMUXRTL_INTERFACES
    85: pkg_requires = ['flx_pthread', 'flx_rtl'] # flx_rtl for config .hpp
    86: lib_requires = ['libflx_pthread']  # however libflx not needed
    87: dflags = EXTRA_SYS_LIBS
    88: sflags = EXTRA_SYS_LIBS
    89: iscr_source = [
    90:   "lpsrc/flx_demux.pak",
    91:   "lpsrc/flx_demuxconfig.pak",
    92:   ]
    93: build_macro = "DEMUX"
    94: weaver_directory = 'doc/rtl/flx_demux/'
    95: 
End python section to spkgs/demux.py[1]
Start cpp section to demux/demux_sockety.cpp[1 /1 ]
     1: #line 127 "./lpsrc/flx_demuxconfig.pak"
     2: #include "demux_sockety.hpp" /* for this stuff */
     3: 
     4: #include <stdio.h>        /* for perror */
     5: #include <fcntl.h>        /* for making non blocking sockets */
     6: #include <netinet/in.h>     /* for sockaddr_in */
     7: #include <arpa/inet.h>      /* for inet_addr */
     8: #include <unistd.h>       /* for close */
     9: 
    10: #include <netinet/in.h>     /* IPPROTO_TCP and sockaddr_in */
    11: #include <netinet/tcp.h>    /* TCP_NODELAY */
    12: 
    13: #include <sys/types.h>      /* for accept */
    14: #include <sys/socket.h>
    15: //#include <sys/errno.h>    /* EINPROGRESS (GUSI doesn't like both this and errno.h)*/
    16: 
    17: #include <errno.h>        /* errno */
    18: 
    19: #include <string.h>       /* for memset */
    20: 
    21: typedef socklen_t FLX_SOCKLEN_T;
    22: 
    23: namespace flx { namespace demux {
    24: 
    25: /*
    26:  returns a socket ready for listening (AF_INET, SOCK_STREAM for now).
    27:  0 in for port means let kernel decide, result in *io_port
    28:  portable, can be factored out. listens on all NICs.
    29:  returns -1 on failure, sometimes eats errno.
    30:  p.s. sets SO_REUSEADDR.
    31: */
    32: int
    33: create_listener_socket(int* io_port, int q_len)
    34: {
    35:   int         listener;
    36:   int         yes = 1;  /* for address reuse */
    37: 
    38:   if((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    39:     return -1;
    40: 
    41:   /* get rid of those *pesky* "address already in use" errors. */
    42:   /* for when you don't cleanly shutdown the server */
    43:   if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1)
    44:     goto listener_fail;
    45: 
    46:   /* bind listener to local interface (ANY) */
    47:   if(bind_sock(listener, io_port) == -1)
    48:     goto listener_fail;
    49: 
    50:   /* set listen queue length for socket */
    51:   if(listen(listener, q_len) == -1)
    52:     goto listener_fail;
    53: 
    54:   return listener;
    55: 
    56: listener_fail:
    57:   perror("create_listener_socket"); /* eats errno! */
    58:   if(close(listener) == -1)
    59:     perror("create_listener_socket close");
    60:   return -1;
    61: }
    62: 
    63: /* create listener, make it non-blocking */
    64: /* duh, sometimes eats errno...*/
    65: int
    66: create_async_listener(int* io_port, int q_len)
    67: {
    68:   int   listener;
    69: 
    70:   listener = create_listener_socket(io_port, q_len);
    71: 
    72:   if(-1 == listener) return -1;
    73: 
    74:   if(make_nonblock(listener) == -1)
    75:   {
    76:     if(close(listener) != 0)
    77:       perror("create_async_listener close");
    78:     return -1;
    79:   }
    80: 
    81:   return listener;
    82: }
    83: 
    84: /* ps, sets resulting socket to non-block. some people would say that */
    85: /* this WASN'T nice, so change the name some time. returns socket or -1 */
    86: /* on failure, with *err containing the error code. on success returns 0 */
    87: /* with zero (= no error) in *err */
    88: int
    89: nice_accept(int listener, int* err)
    90: {
    91:   struct sockaddr_in  remoteaddr;
    92:   /*socklen_t     addrlen = sizeof(remoteaddr);*/
    93:   /* os x 10.2.8 doesn't have socklen_t. will this work elsewhere? */
    94:   /* 10.4 (gcc 4.0) complains about signedeness, so now unsigned */
    95:   FLX_SOCKLEN_T addrlen = sizeof(remoteaddr);
    96:   int         newfd;
    97: 
    98:   *err = 0;     /* assume all good */
    99: 
   100:   newfd = accept(listener, (struct sockaddr*)&remoteaddr, &addrlen);
   101:   if(-1 == newfd) {
   102:     *err = errno;
   103:     return -1;
   104:   }
   105:   else
   106:   {
   107:     /*I think 0's the result I want*/
   108:     if(make_nonblock(newfd) == -1)
   109:     {
   110:       *err = errno;
   111: 
   112:       /* bizarre case, note that close's errno is lost */
   113:       if(close(newfd) == -1)
   114:         perror("nice_accept close");
   115:       newfd = -1;
   116:     }
   117:   }
   118:   return newfd;
   119: }
   120: 
   121: /* call this connect_ipv4? would its interface work for ipv6? */
   122: /* this connect can be either asynchronous or synchronous, */
   123: /* depending on whether or not the socket is non blocking */
   124: /* returns -1 with err in errno on failure */
   125: int
   126: connect_sock(int s, const char* addr, int port)
   127: {
   128:   struct sockaddr_in  sock_addr;
   129: 
   130:   memset(&sock_addr, 0, sizeof(sock_addr));
   131:   sock_addr.sin_family = AF_INET;     /* host byte order */
   132:   sock_addr.sin_addr.s_addr = inet_addr(addr);
   133:   sock_addr.sin_port = htons(port);
   134: 
   135:   return connect(s, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
   136: }
   137: 
   138: /* bind s to local address with given port number, or zero to let OS */
   139: /* choose. can you bind to non-local addresses? not sure, but you might */
   140: /* like to choose which local interface... (ADD OTHER INTERFACES HERE) */
   141: /* returns -1 on failure with error code in errno */
   142: int
   143: bind_sock(int s, int* io_port)
   144: {
   145:   struct sockaddr_in  addr;
   146:   FLX_SOCKLEN_T namelen = sizeof(addr);
   147: 
   148:   memset(&addr, 0, sizeof(addr));
   149:   addr.sin_family = AF_INET;      /* host byte order */
   150:   /* make the NIC an argument */
   151:   addr.sin_addr.s_addr = htonl(INADDR_ANY); /* allow multihomed */
   152:   addr.sin_port = htons(*io_port);
   153: 
   154:   /* bind to port */
   155:   if (bind(s, (struct sockaddr *)&addr, namelen) < 0)
   156:   {
   157:     return -1;
   158:   }
   159: 
   160:   /* we don't need to do this when the port was specified */
   161:   if(0 == *io_port)
   162:   {
   163:     /* Find out what port number was chosen */
   164:     if (getsockname(s, (struct sockaddr *)&addr, &namelen) < 0)
   165:     {
   166:       return -1;
   167:     }
   168: 
   169:     *io_port = ntohs(addr.sin_port);
   170:   }
   171: 
   172:   return 0; /* success! */
   173: }
   174: 
   175: /* simple wrapper for fcntl for those too lazy to look it up */
   176: /* returns -1 on failure with errno set or non -1  otherwise */
   177: int
   178: make_nonblock(int s)
   179: {
   180:   return fcntl(s, F_SETFL, O_NONBLOCK);
   181: }
   182: 
   183: /* returns -1 on failure with errno set or 0 otherwise */
   184: int
   185: set_tcp_nodelay(int s, int disable_nagle)
   186: {
   187:   return setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
   188:     (char*)&disable_nagle, sizeof(disable_nagle));
   189: }
   190: 
   191: /*
   192:     Getting the determining if the async connect succeeded and if not,
   193:     its error, can actually be quite hairy on some systems, see
   194:     http://cr.yp.to/docs/connect.html
   195:     for suggestions (none of which I follow at this point)
   196:   returns 0 on success and socket error in *socket_err
   197:   on failure returns -1 and *socket_err errno
   198: */
   199: int
   200: get_socket_error(int s, int* socket_err)
   201: {
   202:   int       res;
   203:     FLX_SOCKLEN_T len = sizeof(*socket_err);
   204:     /* god knows what the level should be. socket level seems sensible. */
   205:     res = getsockopt(s, SOL_SOCKET, SO_ERROR, socket_err, &len);
   206: 
   207:     /* I've heard of impls of getsockopt(SO_ERROR) acting as they they */
   208:     /* had the socket error (i.e. returning -1 and the sock err in errno) */
   209:     if(-1 == res)
   210:     {
   211:         *socket_err = errno;     // don't think its ours
   212:         fprintf(stderr, "getsockopt failed - is that our error? (%i)\n",
   213:             *socket_err);
   214:     }
   215: 
   216:   return res;
   217: }
   218: 
   219: /* also make non-blocking AFTER connect, that is, */
   220: /* this is a synchronous connect */
   221: /* is eating errno, fix */
   222: int
   223: nice_connect(const char* addr, int port)
   224: {
   225:   int     s;
   226: 
   227:   if((s = socket(AF_INET, SOCK_STREAM, 0)) != -1
   228:     && connect_sock(s, addr, port) == 0
   229:     && make_nonblock(s) != -1)
   230:   {
   231:     return s;   /* success! */
   232:   }
   233: 
   234:   /* something happened (not as good as catch 22) */
   235:   perror("nice_connect");
   236: 
   237:   if(-1 != s && close(s) != 0)
   238:     perror("nice close");
   239: 
   240:   return -1;
   241: }
   242: 
   243: /* makes the socket non-blocking BEFORE connect, returns result */
   244: /* from which can be determined if it finished immediately */
   245: /* returns the socket & finished flag or -1 on failure, with the */
   246: /* error returned in *err */
   247: int
   248: async_connect(const char* addr, int port, int* finished, int* err)
   249: {
   250:   int     s = -1;
   251: 
   252:   if((s = socket(AF_INET, SOCK_STREAM, 0)) != -1 && make_nonblock(s) != -1)
   253:   {
   254:     /* no error we now have s, a non-blocking socket */
   255:     if(connect_sock(s, addr, port) == 0)
   256:     {
   257:       *err = 0;         /* no error */
   258:       *finished = 1;        /* finished */
   259:       return s;
   260:     }
   261: 
   262:     *err = errno;         /* connect failed or in-progress */
   263: 
   264:     /* this can apparently be EWOULDBLOCK or even EAGAIN on some systems */
   265:     /* any info? on some systems they're the same, on some they're not */
   266:     if(EINPROGRESS == *err)
   267:     {
   268:       *finished = 0;        /* not finished, in progress */
   269:       return s;
   270:     }
   271:     /* some other failure, fall through and clean up */
   272:   }
   273: 
   274:   /* hope you can read same errno twice in threaded apps! */
   275:   *err = errno;           /* pass back error */
   276: 
   277:   if(-1 != s && close(s) != 0)    /* we lose the close error */
   278:     perror("async_connect close");
   279: 
   280:   *finished = 1;            /* for completeness */
   281:   return -1;
   282: }
   283: }}
   284: 
End cpp section to demux/demux_sockety.cpp[1]