[bind10-dev] Socket creator and low-level code

JINMEI Tatuya / 神明達哉 jinmei at isc.org
Thu Oct 21 15:26:45 UTC 2010


At Thu, 21 Oct 2010 09:18:44 +0200,
Michal 'vorner' Vaner <michal.vaner at nic.cz> wrote:

> template<typename T>
> bool
> readVar(int fd, T &variable) {
>   return (read_data(fd, &variable, sizeof(typename T)) == sizeof(typename T));
> }
> 
> This is much more usable. Does it seem right for you as well, regarding the
> pointer-cleanness and so? It solves even the wrong-length bug and in case

Hmm, I think I can live with that.

But, I'm still not so happy with read_data() manipulating the buffer
with low level pointer arithmetic.  I'd suggest either

- using a safe interface such as std::vector if we need to keep the IO
  primitive that needs to expect partial read, or
- use a real socket with recv(MSG_WAITALL).  then we don't even have
  to need a separate read_data function.  it can simply be:
  return (recv(fd, &variable, sizeof(T), MSG_WAITALL) == sizeof(T));
  or
- if we want to keep using stdin and stdout, use std::iostream instead
  of the lower level API

> someone would like to send more complicated data structures (like std::string),
> a template-specified function could be written and solve it (thought I doubt
> there will be need for that any time).

std::string won't work with this approach, because passing an address
to an object of std::string is meaningless.

> There are 2 more places where pointers are used. There's memset, because the
> sockaddr_* structures have no constructors. It could be overcome by using a
> global variable (so it is zeroed at the start of program) at the cost of reusing
> it.

I can live with such localized use of memset(0).

> Other place is the interface of BSD sockets, namely bind. I have no idea what to
> do with this. But I use it only as a reference to the correct sockaddr_*
> structure. I maybe should add an assert to ensure it is really set.

This is also okay for me.  At interfaces to lowest level system call,
passing a row pointer is inevitable.

Having said that, I would actually propose one different type of
approach, not actually related to the pointer vs higher-level API
discussion.

I wonder whether we can pass addresses and ports as a string, which
will be represented in the form of length + C-string.  Then we can use
getaddrinfo(3) to support both IPv4 and IPv6 in unified code, without
worrying about portability of sa_len (btw your current code has this
portability bug).  The main drawback of this approach is exchanging
variable-length data may be considered riskier, but, I would accept
that risk if we use safer API.

---
JINMEI, Tatuya
Internet Systems Consortium, Inc.



More information about the bind10-dev mailing list