diff options
Diffstat (limited to 'src/remoteinfo.c')
-rw-r--r-- | src/remoteinfo.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/remoteinfo.c b/src/remoteinfo.c new file mode 100644 index 0000000..665d2e5 --- /dev/null +++ b/src/remoteinfo.c @@ -0,0 +1,102 @@ +#include <unistd.h> +#include "fmt.h" +#include "buffer.h" +#include "socket_if.h" +#include "error.h" +#include "iopause.h" +#include "timeoutconn.h" +#include "dnsresolv.h" +#include "remoteinfo.h" + +static struct taia now; +static struct taia deadline; + +static int mywrite(int fd,char *buf,int len) +{ + iopause_fd x; + int r; + + x.fd = fd; + x.events = IOPAUSE_WRITE; + for (;;) { + taia_now(&now); + r = iopause(&x,1,&deadline,&now); + if (r > 0 && x.revents) break; + if (taia_less(&deadline,&now)) { + errno = ETIMEDOUT; + return -1; + } + } + return write(fd,buf,len); +} + +static int myread(int fd,char *buf,int len) +{ + iopause_fd x; + int r; + + x.fd = fd; + x.events = IOPAUSE_READ; + for (;;) { + taia_now(&now); + r = iopause(&x,1,&deadline,&now); + if (r > 0 && x.revents) break; + if (taia_less(&deadline,&now)) { + errno = ETIMEDOUT; + return -1; + } + } + return read(fd,buf,len); +} + +static int doit(stralloc *out,int s,char ipremote[16],uint16 portremote,char iplocal[16],uint16 portlocal,unsigned int timeout,uint32 netif) +{ + buffer b; + char bspace[128]; + char strnum[FMT_ULONG]; + int numcolons; + char ch; + + if (socket_bind(s,iplocal,0,netif) == -1) return -1; + if (timeoutconn(s,ipremote,113,timeout,netif) == -1) return -1; + + buffer_init(&b,(ssize_t (*)())mywrite,s,bspace,sizeof(bspace)); + buffer_put(&b,strnum,fmt_ulong(strnum,portremote)); + buffer_put(&b," , ",3); + buffer_put(&b,strnum,fmt_ulong(strnum,portlocal)); + buffer_put(&b,"\r\n",2); + if (buffer_flush(&b) == -1) return -1; + + buffer_init(&b,(ssize_t (*)())myread,s,bspace,sizeof(bspace)); + numcolons = 0; + for (;;) { + if (buffer_get(&b,&ch,1) != 1) return -1; + if ((ch == ' ') || (ch == '\t') || (ch == '\r')) continue; + if (ch == '\n') return 0; + if (numcolons < 3) { + if (ch == ':') ++numcolons; + } + else { + if (!stralloc_append(out,&ch)) return -1; + if (out->len > 256) return 0; + } + } +} + +int remoteinfo(stralloc *out,char ipremote[16],uint16 portremote,char iplocal[16],uint16 portlocal,unsigned int timeout,uint32 netif) +{ + int s; + int r; + + if (!stralloc_copys(out,"")) return -1; + + taia_now(&now); + taia_uint(&deadline,timeout); + taia_add(&deadline,&now,&deadline); + + s = socket_tcp(); + if (s == -1) return -1; + r = doit(out,s,ipremote,portremote,iplocal,portlocal,timeout,netif); + close(s); + return r; +} |