akaros/user/parlib/net.c
<<
>>
Prefs
   1/* Copyright (c) 2014 The Regents of the University of California
   2 * Barret Rhoden <brho@cs.berkeley.edu>
   3 * See LICENSE for details.
   4 *
   5 * Networking helpers for dealing with the plan 9 interface. */
   6
   7#include <stdlib.h>
   8#include <parlib/stdio.h>
   9#include <string.h>
  10#include <unistd.h>
  11#include <parlib/assert.h>
  12#include <parlib/net.h>
  13
  14#include <sys/types.h>
  15#include <sys/stat.h>
  16#include <fcntl.h>
  17
  18/* my cheap dial, assumes either /net/ or a protocol first, with !s btw the
  19 * proto, host, and port.  it also will modify addr temporarily.  */
  20int cheap_dial(char *addr, char *local, char *dir, int *cfdp)
  21{
  22        int ret, ctlfd, datafd, conv_id;
  23        char *prefix;
  24        char *hostname;                         /* including !port */
  25        size_t buf_len = strlen(addr) + 30;     /* 30 should be enough extra */
  26        char *buf = malloc(buf_len);
  27        if (!buf) {
  28                perror("Unable to malloc buf!");
  29                return -1;
  30        }
  31        if (local || dir) {
  32                perror("Cheap dial doesn't support local or dir");
  33                ret = -1;
  34                goto out_buf;
  35        }
  36        hostname = strchr(addr, '!');
  37        if (!hostname) {
  38                perror("No first bang");
  39                ret = -1;
  40                goto out_buf;
  41        }
  42        *hostname++ = '\0';
  43        prefix = (addr[0] == '/' ? "" : "/net/");
  44        ret = snprintf(buf, buf_len, "%s%s/clone", prefix, addr);
  45        if (snprintf_error(ret, buf_len)) {
  46                perror("Clone chan path too long");
  47                ret = -1;
  48                goto out_readdr;
  49        }
  50        ctlfd = open(buf, O_RDWR);
  51        if (ctlfd < 0) {
  52                perror("Can't clone a conversation");
  53                ret = -1;
  54                goto out_readdr;
  55        }
  56        ret = read(ctlfd, buf, buf_len - 1);
  57        if (ret <= 0) {
  58                if (!ret)
  59                        printf("Got early EOF from ctl\n");
  60                else
  61                        perror("Can't read ctl");
  62                ret = -1;
  63                goto out_ctlfd;
  64        }
  65        buf[ret] = 0;
  66        conv_id = atoi(buf);
  67        ret = snprintf(buf, buf_len, "connect %s", hostname);
  68        if (snprintf_error(ret, buf_len)) {
  69                perror("Connect string too long");
  70                ret = -1;
  71                goto out_ctlfd;
  72        }
  73        if ((write(ctlfd, buf, strlen(buf)) <= 0)) {
  74                perror("Failed to connect");
  75                ret = -1;
  76                goto out_ctlfd;
  77        }
  78        ret = snprintf(buf, buf_len, "%s%s/%d/data", prefix, addr, conv_id);
  79        if (snprintf_error(ret, buf_len)) {
  80                perror("Data chan path too long");
  81                ret = -1;
  82                goto out_ctlfd;
  83        }
  84        datafd = open(buf, O_RDWR);
  85        if (datafd < 0) {
  86                perror("Failed to open data chan");
  87                ret = -1;
  88                goto out_ctlfd;
  89        }
  90        if (cfdp)
  91                *cfdp = ctlfd;
  92        else
  93                close(ctlfd);
  94        ret = datafd;
  95        /* skip over the ctlfd close */
  96        goto out_readdr;
  97
  98out_ctlfd:
  99        close(ctlfd);
 100out_readdr:
 101        /* restore the change we made to addr */
 102        *--hostname = '!';
 103out_buf:
 104        free(buf);
 105        return ret;
 106}
 107