int mu_streamref_create_abridged (mu_stream_t *pref, mu_stream_t str, mu_off_t start, mu_off_t end) { int rc; mu_off_t off; int flags; struct _mu_streamref *sp; rc = mu_stream_seek (str, 0, MU_SEEK_SET, &off);/*FIXME: SEEK_CUR?*/ if (rc) return rc; mu_stream_get_flags (str, &flags); sp = (struct _mu_streamref *) _mu_stream_create (sizeof (*sp), flags | _MU_STR_OPEN); if (!sp) return ENOMEM; mu_stream_ref (str); sp->stream.read = _streamref_read; if (str->readdelim) sp->stream.readdelim = _streamref_readdelim; sp->stream.write = _streamref_write; sp->stream.flush = _streamref_flush; sp->stream.open = _streamref_open; sp->stream.close = _streamref_close; sp->stream.done = _streamref_done; sp->stream.seek = _streamref_seek; sp->stream.size = _streamref_size; sp->stream.ctl = _streamref_ctl; sp->stream.wait = _streamref_wait; sp->stream.truncate = _streamref_truncate; sp->stream.shutdown = _streamref_shutdown; sp->stream.error_string = _streamref_error_string; sp->transport = str; sp->start = start; sp->end = end; if (off < start || off > end) off = start; sp->offset = off; *pref = (mu_stream_t) sp; mu_stream_set_buffer (*pref, mu_buffer_full, 0); return 0; }
static int _tcp_open (mu_stream_t stream) { struct _tcp_instance *tcp = (struct _tcp_instance *)stream; int flgs, ret; socklen_t namelen; struct sockaddr_in peer_addr; int flags; mu_stream_get_flags (stream, &flags); switch (tcp->state) { case TCP_STATE_INIT: if (tcp->fd == -1) { tcp->fd = socket (tcp->remote_addr->addr->sa_family, SOCK_STREAM, 0); if (tcp->fd == -1) return errno; } if (flags & MU_STREAM_NONBLOCK) { flgs = fcntl (tcp->fd, F_GETFL); flgs |= O_NONBLOCK; fcntl (tcp->fd, F_SETFL, flgs); mu_stream_set_flags (stream, MU_STREAM_NONBLOCK); } if (tcp->source_addr) { if (bind (tcp->fd, tcp->source_addr->addr, tcp->source_addr->addrlen) < 0) { int e = errno; close (tcp->fd); tcp->fd = -1; return e; } } tcp->state = TCP_STATE_RESOLVING; case TCP_STATE_RESOLVING: tcp->state = TCP_STATE_RESOLVE; case TCP_STATE_RESOLVE: if (connect (tcp->fd, tcp->remote_addr->addr, tcp->remote_addr->addrlen) == -1) { ret = errno; if (ret == EINPROGRESS || ret == EAGAIN) { tcp->state = TCP_STATE_CONNECTING; ret = EAGAIN; } else _tcp_close (stream); return ret; } tcp->state = TCP_STATE_CONNECTING; case TCP_STATE_CONNECTING: namelen = sizeof (peer_addr); if (getpeername (tcp->fd, (struct sockaddr *) &peer_addr, &namelen) == 0) tcp->state = TCP_STATE_CONNECTED; else { ret = errno; _tcp_close (stream); return ret; } break; } return 0; }