<div dir="ltr">Hey Rusty,
<div><br></div><div>What do you think about the following code design?  I've not even compiled it but i'm dropping it here for suggestions.</div><div><br></div><div><div>#ifndef _SOCKET_H</div><div>#define _SOCKET_H</div>
<div><br></div><div>#include <csnippets/list.h></div><div>#include <csnippets/pollevent.h></div><div><br></div><div>#include <time.h></div><div>#include <pthread.h></div><div><br></div><div>struct sk_buff {</div>
<div><span class="Apple-tab-span" style="white-space:pre">      </span>/** The data read from a recv() syscall  */</div><div><span class="Apple-tab-span" style="white-space:pre">  </span>void *data;</div><div><span class="Apple-tab-span" style="white-space:pre">  </span>/** length of @data.  */</div>
<div><span class="Apple-tab-span" style="white-space:pre">      </span>size_t size;</div><div>};</div><div><br></div><div>struct listener {</div><div><span class="Apple-tab-span" style="white-space:pre">       </span>int fd;                         /* Socket file descriptor.  */</div>
<div><br></div><div><span class="Apple-tab-span" style="white-space:pre">     </span>struct list_head children;      /* List of connections (struct conn) */</div><div><span class="Apple-tab-span" style="white-space:pre">      </span>unsigned int num_connections;   /* Current active connections */</div>
<div><br></div><div><span class="Apple-tab-span" style="white-space:pre">     </span>void (*on_accept) (struct listener *self, struct conn *conn);</div><div>};</div><div><br></div><div>struct conn {</div><div><span class="Apple-tab-span" style="white-space:pre">  </span>int fd;<span class="Apple-tab-span" style="white-space:pre">                     </span>/* The socket file descriptor */</div>
<div><span class="Apple-tab-span" style="white-space:pre">      </span>char host[1025];<span class="Apple-tab-span" style="white-space:pre">    </span>/* The hostname of this connection */</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>char port[32];<span class="Apple-tab-span" style="white-space:pre">              </span>/* The port we're connected to */</div>
<div><span class="Apple-tab-span" style="white-space:pre">      </span>char remote[1025];<span class="Apple-tab-span" style="white-space:pre">  </span>/* Who did we connect to?  Or who did we come from?  */</div><div><span class="Apple-tab-span" style="white-space:pre">      </span>time_t last_active;<span class="Apple-tab-span" style="white-space:pre"> </span>/* The timestamp of last activity.  Useful for PING PONG. */</div>
<div><br></div><div><span class="Apple-tab-span" style="white-space:pre">     </span>/* "write buffer" this is changed whenever data has been been sent.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> * If the data was successfully sent over the connection, ops.write will be</div>
<div><span class="Apple-tab-span" style="white-space:pre">      </span> * called.  */</div><div><span class="Apple-tab-span" style="white-space:pre">       </span>struct sk_buff wbuff;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>struct list_node node;<span class="Apple-tab-span" style="white-space:pre">      </span>     /* next and previous conn */</div>
<div>};</div><div>struct io_service;</div><div><br></div><div>#define __ct_typecheck(__type, __desired_type)       \</div><div><span class="Apple-tab-span" style="white-space:pre">      </span>((void)sizeof(char[1 - 2 * !__builtin_types_compatible_p(__typeof__((type)), __typeof__((__desired_type)))]))</div>
<div><br></div><div>typedef void (*conn_callback) (void *, void *);</div><div>#define conn_register_cb(conn,  ccb, cb) \</div><div><span class="Apple-tab-span" style="white-space:pre">      </span>__ct_typecheck(conn, struct conn);  __ct_typecheck(cb, conn_callback); \</div>
<div><span class="Apple-tab-span" style="white-space:pre">      </span>_conn_register_cb((conn), (ccb), (cb))</div><div><br></div><div>typedef enum {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>CB_READ,</div>
<div><span class="Apple-tab-span" style="white-space:pre">      </span>CB_WRITE,</div><div><span class="Apple-tab-span" style="white-space:pre">    </span>CB_DISCONNECT,</div><div><span class="Apple-tab-span" style="white-space:pre">       </span>CB_CONNECT</div>
<div>} conn_callback_t;</div><div><br></div><div>typedef void (*listener_callback) (void *, void *);</div><div>#define listener_register_callback(listener, cb) \</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>__ct_typecheck(listener, struct listener); __ct_typecheck(cb, void (*) (struct listener *, struct conn *)); \</div>
<div><span class="Apple-tab-span" style="white-space:pre">      </span>_listener_register_callback((listener), (cb))</div><div><br></div><div>struct listener *listener_new(struct io_service *io, const char *address, const char *service,</div>
<div><span class="Apple-tab-span" style="white-space:pre">                              </span>unsigned long max_conns);</div><div>int _listener_register_callback(struct listener *listener, listener_callback cb);</div><div><br></div><div>int listener_accept(struct listener *li, struct conn **to);</div>
<div>int listener_accept_next(struct listener *li, struct conn **to, listener_callback cb);</div><div><br></div><div>struct conn *conn_new(struct io_service *io, const char *hostname, const char *port);</div><div>int _conn_register_callback(struct conn *conn, const conn_callback_t ccb, conn_callback cb);</div>
<div><br></div><div>ssize_t conn_write(struct conn *conn, const void *data, size_t dlen);</div><div>ssize_t conn_write_next(struct conn *conn, const void *data, size_t dlen,</div><div><span class="Apple-tab-span" style="white-space:pre">                 </span>conn_callback cb);</div>
<div>ssize_t conn_read(struct conn *conn, const void *data, size_t dlen);</div><div>ssize_t conn_read_next(struct conn *conn, const void *data, size_t dlen,</div><div><span class="Apple-tab-span" style="white-space:pre">                    </span>conn_callback cb);</div>
<div><br></div><div>int service_poll(struct io_service *service);</div><div>int service_remove_listener(struct io_service *service, struct listener *listener);</div><div>int service_remove_conn(struct io_service *service, struct conn *conn);</div>
<div><br></div><div>#endif    /* _SOCKET_H */</div><div><br></div></div><div>Thanks,</div><div>Allan</div></div>