freely copy it. */
/* Everyone is also guaranteed that all padding is set to zero, ie
that comm_addrs referring to semantically identical peers will
- compare equal with memcmp. Anyone who constructs a comm_addr
- must start by memsetting it with FILLZERO, or some
- equivalent. */
+ compare equal with memcmp. */
struct comm_if *comm;
- struct sockaddr_in sin;
+ union {
+ struct sockaddr_in sin;
+ } priv;
};
/* Return True if the packet was processed, and shouldn't be passed to
comm_notify_fn *fn);
typedef bool_t comm_sendmsg_fn(void *commst, struct buffer_if *buf,
const struct comm_addr *dest);
+typedef bool_t comm_addr_construct_fn(void *commst, struct comm_addr *ca,
+ const struct sockaddr_in *sin);
+ /* Fills in ca->comm an ca->priv. *sin must have no nonzero padding,
+ so must have been FILLZERO'd before its useful fields were filled in.
+ The resulting ca->comm has been constructed likewise, as required
+ above. On failure, logs error, returns false on failure.*/
typedef const char *comm_addr_to_string_fn(void *commst,
const struct comm_addr *ca);
/* Returned string is in a static buffer. */
comm_request_notify_fn *request_notify;
comm_release_notify_fn *release_notify;
comm_sendmsg_fn *sendmsg;
+ comm_addr_construct_fn *addr_construct;
comm_addr_to_string_fn *addr_to_string;
};
static void site_resolve_callback(void *sst, struct in_addr *address)
{
struct site *st=sst;
- struct comm_addr ca_buf, *ca_use;
+ struct comm_addr ca_buf, *ca_use=0;
if (st->state!=SITE_RESOLVE) {
slog(st,LOG_UNEXPECTED,"site_resolve_callback called unexpectedly");
return;
}
if (address) {
- FILLZERO(ca_buf);
- ca_buf.comm=st->comms[0];
- ca_buf.sin.sin_family=AF_INET;
- ca_buf.sin.sin_port=htons(st->remoteport);
- ca_buf.sin.sin_addr=*address;
- ca_use=&ca_buf;
+ struct sockaddr_in sin;
+ FILLZERO(sin);
+ sin.sin_family=AF_INET;
+ sin.sin_port=htons(st->remoteport);
+ sin.sin_addr=*address;
+ if (st->comms[0]->addr_construct(st->comms[0]->st, &ca_buf, &sin)) {
+ ca_use=&ca_buf;
+ }
} else {
slog(st,LOG_ERROR,"resolution of %s failed",st->address);
- ca_use=0;
}
if (transport_compute_setupinit_peers(st,ca_use)) {
enter_new_state(st,SITE_SENTMSG1);
la.sin_port=htons(st->port);
snprintf(sbuf, sizeof(sbuf), "udp:%s-%s",
- saddr_to_string(&la), saddr_to_string(&ca->sin));
+ saddr_to_string(&la), saddr_to_string(&ca->priv.sin));
return sbuf;
}
+static bool_t addr_construct(void *commst, struct comm_addr *ca,
+ const struct sockaddr_in *sin) {
+ struct udp *st=commst;
+ FILLZERO(*ca);
+ ca->comm=&st->ops;
+ ca->priv.sin=*sin;
+ return True;
+}
+
static int udp_beforepoll(void *state, struct pollfd *fds, int *nfds_io,
int *timeout_io)
{
struct comm_addr ca;
FILLZERO(ca);
ca.comm=&st->ops;
- ca.sin=from;
+ ca.priv.sin=from;
if (n->fn(n->state, st->rbuf, &ca)) {
done=True;
break;
if (st->use_proxy) {
sa=buf->start-8;
- memcpy(sa,&dest->sin.sin_addr,4);
+ memcpy(sa,&dest->priv.sin.sin_addr,4);
memset(sa+4,0,4);
- memcpy(sa+6,&dest->sin.sin_port,2);
+ memcpy(sa+6,&dest->priv.sin.sin_port,2);
sendto(st->fd,sa,buf->size+8,0,(struct sockaddr *)&st->proxy,
sizeof(st->proxy));
} else {
sendto(st->fd, buf->start, buf->size, 0,
- (struct sockaddr *)&dest->sin, sizeof(dest->sin));
+ (struct sockaddr *)&dest->priv.sin, sizeof(dest->priv.sin));
}
return True;
st->ops.request_notify=request_notify;
st->ops.release_notify=release_notify;
st->ops.sendmsg=udp_sendmsg;
+ st->ops.addr_construct=addr_construct;
st->ops.addr_to_string=addr_to_string;
st->port=0;
st->use_proxy=False;