Example #1
0
coroutine void dialogue(tcpsock as, chan ch) {
    chs(ch, int, CONN_ESTABLISHED);

    int64_t deadline = now() + 10000;

    tcpsend(as, "What's your name?\r\n", 19, deadline);
    if(errno != 0)
        goto cleanup;
    tcpflush(as, deadline);
    if(errno != 0)
        goto cleanup;

    char inbuf[256];
    size_t sz = tcprecvuntil(as, inbuf, sizeof(inbuf), "\r", 1, deadline);
    if(errno != 0)
        goto cleanup;

    inbuf[sz - 1] = 0;
    char outbuf[256];
    int rc = snprintf(outbuf, sizeof(outbuf), "Hello, %s!\r\n", inbuf);

    sz = tcpsend(as, outbuf, rc, deadline);
    if(errno != 0)
        goto cleanup;
    tcpflush(as, deadline);

    cleanup:
    if(errno == 0)
        chs(ch, int, CONN_SUCCEEDED);
    else
        chs(ch, int, CONN_FAILED);
    tcpclose(as);
}
coroutine void dialogue(tcpsock as) {
    int64_t deadline = now() + 10000;

    tcpsend(as, "What's your name?\r\n", 19, deadline);
    if(errno != 0)
        goto cleanup;
    tcpflush(as, deadline);
    if(errno != 0)
        goto cleanup;

    char inbuf[256];
    size_t sz = tcprecvuntil(as, inbuf, sizeof(inbuf), "\r", 1, deadline);
    if(errno != 0)
        goto cleanup;

    inbuf[sz - 1] = 0;
    char outbuf[256];
    int rc = snprintf(outbuf, sizeof(outbuf), "Hello, %s!\r\n", inbuf);

    sz = tcpsend(as, outbuf, rc, deadline);
    if(errno != 0)
        goto cleanup;
    tcpflush(as, deadline);
    if(errno != 0)
        goto cleanup;

    cleanup:
    tcpclose(as);
}
Example #3
0
File: step2.c Project: 8l/libmill
int main(int argc, char *argv[]) {

    int port = 5555;
    if(argc > 1)
        port = atoi(argv[1]);

    tcpsock ls = tcplisten(iplocal(NULL, port, 0));
    if(!ls) {
        perror("Can't open listening socket");
        return 1;
    }

    while(1) {
        tcpsock as = tcpaccept(ls, -1);

        tcpsend(as, "What's your name?\r\n", 19, -1);
        tcpflush(as, -1);

        char inbuf[256];
        size_t sz = tcprecvuntil(as, inbuf, sizeof(inbuf), "\r", 1, -1);

        inbuf[sz - 1] = 0;
        char outbuf[256];
        int rc = snprintf(outbuf, sizeof(outbuf), "Hello, %s!\n", inbuf);

        sz = tcpsend(as, outbuf, rc, -1);
        tcpflush(as, -1);

        tcpclose(as);
    }
}
Example #4
0
size_t wsocksend(wsock s, const void *msg, size_t len, int64_t deadline) {
    if(s->flags & WSOCK_LISTENING) {errno = EOPNOTSUPP; return 0;}
    if(s->flags & WSOCK_BROKEN) {errno = ECONNABORTED; return 0;}
    uint8_t buf[12];
    size_t sz;
    buf[0] = 0x82;
    if(len > 0xffff) {
        buf[1] = 127;
        wsock_putll(buf + 2, len);
        sz = 10;
    }
    else if(len > 125) {
        buf[1] = 126;
        wsock_puts(buf + 2, len);
        sz = 4;
    }
    else {
        buf[1] = (uint8_t)len;
        sz = 2;
    }
    uint8_t mask[4];
    if(s->flags & WSOCK_CLIENT) {
        ((uint16_t*)mask)[0] = (uint16_t)wsock_random();
        ((uint16_t*)mask)[1] = (uint16_t)wsock_random();
        buf[1] |= 0x80;
        memcpy(buf + sz, mask, 4);
        sz += 4;
    }
    tcpsend(s->u, buf, sz, deadline);
    if(errno != 0) {s->flags |= WSOCK_BROKEN; return 0;}
    if(s->flags & WSOCK_CLIENT) {
        /* TODO: Use static buffer or something. This way of implementing
           mapping is performance nightmare. */
        uint8_t *masked = malloc(len);
        if(!masked) {s->flags |= WSOCK_BROKEN; errno = ENOMEM; return 0;}
        size_t i;
        for(i = 0; i != len; ++i)
            masked[i] = ((uint8_t*)msg)[i] ^ mask[i % 4];
        tcpsend(s->u, masked, len, deadline);
        int err = errno;
        free(masked);
        errno = err;
    }
    else {
        tcpsend(s->u, msg, len, deadline);
    }
    if(errno != 0) {s->flags |= WSOCK_BROKEN; return 0;}
    tcpflush(s->u, deadline);
    if(errno != 0) {s->flags |= WSOCK_BROKEN; return 0;}
    return len;
}
Example #5
0
coroutine void client(int port) {
    ipaddr addr = ipremote("127.0.0.1", port, 0, -1);
    tcpsock cs = tcpconnect(addr, -1);
    assert(cs);

    char ipstr[16] = {0};
    ipaddrstr(addr, ipstr);
    assert(errno == 0);
    assert(strcmp(ipstr, "127.0.0.1") == 0);

    int fd = tcpdetach(cs);
    assert(fd != -1);
    cs = tcpattach(fd, 0);
    assert(cs);

    msleep(now() + 100);

    char buf[16];
    size_t sz = tcprecv(cs, buf, 3, -1);
    assert(sz == 3 && buf[0] == 'A' && buf[1] == 'B' && buf[2] == 'C');

    sz = tcpsend(cs, "123\n45\n6789", 11, -1);
    assert(sz == 11 && errno == 0);
    tcpflush(cs, -1);
    assert(errno == 0);

    tcpclose(cs);
}
Example #6
0
int main() {
    tcpsock ls = tcplisten("*:5555");
    assert(ls);

    go(client());

    tcpsock as = tcpaccept(ls);

    tcpsend(as, "ABC", 3);
    int rc = tcpflush(as);
    assert(rc == 0);

    char buf[16];
    ssize_t sz = tcprecvuntil(as, buf, sizeof(buf), '\n');
    assert(sz == 4);
    assert(buf[0] == '1' && buf[1] == '2' && buf[2] == '3' && buf[3] == '\n');
    sz = tcprecvuntil(as, buf, sizeof(buf), '\n');
    assert(sz == 3);
    assert(buf[0] == '4' && buf[1] == '5' && buf[2] == '\n');
    sz = tcprecvuntil(as, buf, 3, '\n');
    assert(sz == 0);
    assert(buf[0] == '6' && buf[1] == '7' && buf[2] == '8');

    tcpclose(as);
    tcpclose(ls);

    return 0;
}
Example #7
0
int main(int argc, char *argv[])
{
    int port = 5555;
    if(argc > 1)
        port = atoi(argv[1]);

    ipaddr  addr    = iplocal(NULL, port, 0);
    tcpsock ls      = tcplisten(addr, 10);
    if(!ls) 
    {
        perror("Can't open listening socket");
        return 1;
    } 

    while(1)
    {
        tcpsock as = tcpaccept(ls, -1);
        printf("New connection!\n");

        tcpsend(as, "What's your name?\r\n", 19, -1);
        tcpflush(as, -1);

        tcpclose(as);
    }

    return 0;
}
// java testButton.
JNIEXPORT void JNICALL
Java_com_projecttango_experiments_nativepointcloud_TangoJNINative_testButton(
    JNIEnv*, jobject) {



float val [8 + 3*2];
//point no
val[0]=3*2;
//zaverage
val[1]=2/2;
//rotation
val[2]=0.0;
val[3]=-1.0;
val[4]=-1.0;
//translation
val[5]=1.0;
val[6]=0.0;
val[7]=1.0;
//points
val[8]=2;
val[9]=2;
val[10]=2;

val[11]=0.0;
val[12]=0.0;
val[13]=0.0;
unsigned int microseconds=50;
while(1){

  tcpsend(val,sizeof(val)/sizeof(val[0]));
  std::this_thread::sleep_for(std::chrono::milliseconds(microseconds));
}
}
Example #9
0
void wsockpong(wsock s, int64_t deadline) {
    if(s->flags & WSOCK_LISTENING) {errno = EOPNOTSUPP; return;}
    if(s->flags & (WSOCK_BROKEN | WSOCK_DONE)) {errno = ECONNABORTED; return;}
    tcpsend(s->u, "\x8A\x00", 2, deadline);
    if(errno != 0) {s->flags |= WSOCK_BROKEN;}
    tcpflush(s->u, deadline);
    if(errno != 0) {s->flags |= WSOCK_BROKEN;}
    errno = 0;
}
Example #10
0
void doconnect(void) {
    ipaddr addr = ipremote("127.0.0.1", 5557, 0, -1);
    tcpsock s = tcpmuxconnect(addr, "foo", -1);
    assert(s);
    tcpsend(s, "abc", 3, -1);
    assert(errno == 0);
    tcpflush(s, -1);
    assert(errno == 0);
}
/*------------------------------------------------------------------------
 *  tcpxmit - handle TCP output events while we are transmitting
 *------------------------------------------------------------------------
 */
int
tcpxmit(int tcbnum, int event)
{
	struct	tcb	*ptcb = &tcbtab[tcbnum];
	void		*tv;
	int		tosend, pending, window;

	if (event == RETRANSMIT) {
		tmclear(tcps_oport, MKEVENT(SEND, tcbnum));
		tcprexmt(tcbnum, event);
		ptcb->tcb_ostate = TCPO_REXMT;
		return OK;
	} /* else SEND */
	tosend = tcphowmuch(ptcb);
	if (tosend == 0) {
		if (ptcb->tcb_flags & TCBF_NEEDOUT)
			tcpsend(tcbnum, TSF_NEWDATA);	/* just an ACK */
		if (ptcb->tcb_snext == ptcb->tcb_suna)
			return OK;
		/* still unacked data; restart transmit timer	*/
		tv = MKEVENT(RETRANSMIT, tcbnum);
		if (!tmleft(tcps_oport, tv))
			tmset(tcps_oport, TCPQLEN, tv, ptcb->tcb_rexmt);
		return OK;
	} else if (ptcb->tcb_swindow == 0) {
		ptcb->tcb_ostate = TCPO_PERSIST;
		ptcb->tcb_persist = ptcb->tcb_rexmt;
		tcpsend(tcbnum, TSF_NEWDATA);
		tmset(tcps_oport, TCPQLEN, MKEVENT(PERSIST,tcbnum),
			ptcb->tcb_persist);
		return OK;
	}	/* else, we have data and window */
	ptcb->tcb_ostate = TCPO_XMIT;
	window = min(ptcb->tcb_swindow, ptcb->tcb_cwnd);
	pending = ptcb->tcb_snext - ptcb->tcb_suna;
	while (tcphowmuch(ptcb) > 0 && pending < window) {
		tcpsend(tcbnum, TSF_NEWDATA);
		pending = ptcb->tcb_snext - ptcb->tcb_suna;
	}
	tv = MKEVENT(RETRANSMIT, tcbnum);
	if (!tmleft(tcps_oport, tv))
		tmset(tcps_oport, TCPQLEN, tv, ptcb->tcb_rexmt);
	return OK;
}
Example #12
0
int mqtt_send_packet(void* socket_info, const void* buf, unsigned int count)
{
	NETSOCKET fd = *((NETSOCKET*)socket_info);
	int ret = 0;

	ret = tcpsend(fd, buf, count);
	if(ret < 0)
		printf("tcp send fail\n");

	return ret;
}
Example #13
0
void handler(tcpsock accepted_socket, chan channel) {
  // request name from connected client
  tcpsend(accepted_socket, "What's your name?\r\n", 19, -1);
  tcpflush(accepted_socket, -1);

  // send a message to the communication channel, signifying this connection
  chs(channel, int, 1);
  
  // capture the name, and create a response message
  char inbuf[256], outbuf[256];
  size_t size = tcprecvuntil(accepted_socket, inbuf, sizeof(inbuf), "\r", 1, -1);
  inbuf[size-1] = 0;
  int rc = snprintf(outbuf, sizeof(outbuf), "Hello, %s!\r\n", inbuf);
  
  // flush the message to the server
  tcpsend(accepted_socket, outbuf, rc, -1);

  cleanup:
    tcpflush(accepted_socket, -1);
    tcpclose(accepted_socket);
}
Example #14
0
void wsockdone(wsock s, int64_t deadline) {
    if(s->flags & WSOCK_LISTENING) {errno = EOPNOTSUPP; return;}
    if(s->flags & WSOCK_BROKEN) {errno = ECONNABORTED; return;}
    if(!(s->flags & WSOCK_DONE)) {
        if(s->flags & WSOCK_DONE) {errno = EPROTO; return;}
        tcpsend(s->u, "\x88\x00", 2, deadline);
        if(errno != 0) {s->flags |= WSOCK_BROKEN;}
        tcpflush(s->u, deadline);
        if(errno != 0) {s->flags |= WSOCK_BROKEN;}
        s->flags |= WSOCK_DONE;
    }
    errno = 0;
}
Example #15
0
void client(void) {
    tcpsock cs = tcpconnect("127.0.0.1:5555");
    assert(cs);

    char buf[16];
    ssize_t sz = tcprecv(cs, buf, 3);
    assert(buf[0] == 'A' && buf[1] == 'B' && buf[2] == 'C');

    tcpsend(cs, "123\n45\n6789", 11);
    int rc = tcpflush(cs);
    assert(rc == 0);

    tcpclose(cs);
}
int main(int argc, char *argv[]) {
    if(argc != 3) {
        printf("usage: c10k <parallel-connections> <roundtrip-count>\n");
        return 1;
    }
    long conns = atol(argv[1]);
    long roundtrips = atol(argv[2]);
    assert(conns >= 1);

    tcpsock ls = tcplisten(iplocal("127.0.0.1", 5555, 0), 10);
    assert(ls);
    int i;
    for(i = 0; i != conns - 1; ++i) {
        go(connector());
        tcpsock as = tcpaccept(ls, -1);
        assert(as);
    }
    go(sender(roundtrips));
    tcpsock as = tcpaccept(ls, -1);
    assert(as);

    int64_t start = now();

    char buf[1];
    size_t nbytes;
    for(i = 0; i != roundtrips; ++i) {
        nbytes = tcpsend(as, "A", 1, -1);
        assert(errno == 0);
        assert(nbytes == 1);
        tcpflush(as, -1);
        assert(errno == 0);
        nbytes = tcprecv(as, buf, 1, -1);
        assert(errno == 0);
        assert(nbytes == 1);
        assert(buf[0] == 'A');
    }

    int64_t stop = now();
    long duration = (long)(stop - start);
    long us = (duration * 1000) / roundtrips;

    printf("done %ld roundtrips in %f seconds\n",
        roundtrips, ((float)duration) / 1000);
    printf("duration of a single roundtrip: %ld us\n", us);
    printf("roundtrips per second: %ld\n",
        (long)(roundtrips * 1000 / duration));

    return 0;
}
static coroutine void sender(long roundtrips) {
    tcpsock s = tcpconnect(iplocal("127.0.0.1", 5555, 0), -1);
    assert(s);
    char buf[1];
    int i;
    size_t nbytes;
    for(i = 0; i != roundtrips; ++i) {
        nbytes = tcprecv(s, buf, 1, -1);
        assert(errno == 0);
        assert(nbytes == 1);
        assert(buf[0] == 'A');
        nbytes = tcpsend(s, "A", 1, -1);
        assert(errno == 0);
        assert(nbytes == 1);
        tcpflush(s, -1);
        assert(errno == 0);
    }
}
Example #18
0
int main() {
    char buf[16];

    tcpsock ls = tcplisten(iplocal(NULL, 5555, 0), 10);
    assert(ls);

    int fd = tcpdetach(ls);
    assert(fd != -1);
    ls = tcpattach(fd, 1);
    assert(ls);
    assert(tcpport(ls) == 5555);

    go(client(5555));

    tcpsock as = tcpaccept(ls, -1);

    /* Test deadline. */
    int64_t deadline = now() + 30;
    size_t sz = tcprecv(as, buf, sizeof(buf), deadline);
    assert(sz == 0 && errno == ETIMEDOUT);
    int64_t diff = now() - deadline;
    assert(diff > -20 && diff < 20); 

    sz = tcpsend(as, "ABC", 3, -1);
    assert(sz == 3 && errno == 0);
    tcpflush(as, -1);
    assert(errno == 0);

    sz = tcprecvuntil(as, buf, sizeof(buf), "\n", 1, -1);
    assert(sz == 4);
    assert(buf[0] == '1' && buf[1] == '2' && buf[2] == '3' && buf[3] == '\n');
    sz = tcprecvuntil(as, buf, sizeof(buf), "\n", 1, -1);
    assert(sz == 3);
    assert(buf[0] == '4' && buf[1] == '5' && buf[2] == '\n');
    sz = tcprecvuntil(as, buf, 3, "\n", 1, -1);
    assert(sz == 3);
    assert(buf[0] == '6' && buf[1] == '7' && buf[2] == '8');

    tcpclose(as);
    tcpclose(ls);

    return 0;
}
Example #19
0
void client(ipaddr addr, int messages, chan results)
{
    int sent = 0;

    tcpsock s = tcpconnect(addr, -1);
    if (s == NULL) {
        perror("tcpconnect");
        goto out;
    }

    while (messages--) {
        tcpsend(s, "hello\n", 6, -1);
        if (errno != 0) {
            perror("tcpsend");
            goto out;
        }

        tcpflush(s, -1);
        if (errno != 0) {
            perror("tcpflush");
            goto out;
        }

        char buf[100];
        size_t sz = tcprecvuntil(s, buf, sizeof(buf), "\n", 1, -1);
        if (errno != 0) {
            perror("tcprecvuntil");
            goto out;
        }
        buf[sz - 1] = 0;
        if (sz != 6) {
            fprintf(stderr, "unexpedted return: %s\n", buf);
            goto out;
        }

        sent++;
    }

out:
    tcpclose(s);
    chs(results, int, sent);
}
Example #20
0
void tcpsendall(int sockid, const char *buff, int len, int maxtime) {
  smallset_t set;
  postime_t end = getcurtime() + maxtime, cur;
  int ret, x;

  set.init(1);
  set.set(0, sockid);

  while (len > 0) {
    while ((cur = getcurtime()) <= end) {
      set.init(1);
      set.set(0, sockid);
      x = end.after(cur);
      if (x > 1000) x = 1000;
      set.waitwrite(x);
      if (set.canwrite(0) || posclient_quitflag) break;
    }
    if (!set.canwrite(0)) throw PException("Could not send buffer");
    ret = tcpsend(sockid, buff, len);

    buff += ret;
    len -= ret;
  }
}
Example #21
0
wsock wsockaccept(wsock s, int64_t deadline) {
    int err = 0;
    if(!(s->flags & WSOCK_LISTENING)) {err = EOPNOTSUPP; goto err0;}
    struct wsock *as = (struct wsock*)malloc(sizeof(struct wsock));
    if(!as) {err = ENOMEM; goto err0;}
    as->flags = 0;
    as->u = tcpaccept(s->u, deadline);
    if(errno != 0) {err = errno; goto err1;}
    wsock_str_init(&as->url, NULL, 0);
    wsock_str_init(&as->subprotocol, NULL, 0);

    /* Parse request. */
    char buf[256];
    size_t sz = wsock_getline(as, buf, sizeof(buf), deadline);
    if(sz < 0) {err = errno; goto err2;}
    char *lend = buf + sz;
    char *wstart = buf;
    char *wend = (char*)memchr(buf, ' ', lend - wstart);
    if(!wend || wend - wstart != 3 || memcmp(wstart, "GET", 3) != 0) {
        err = EPROTO; goto err2;}
    wstart = wend + 1;
    wend = (char*)memchr(wstart, ' ', lend - wstart);
    if(!wend) {err = EPROTO; goto err2;}
    wsock_str_init(&as->url, wstart, wend - wstart);
    wstart = wend + 1;
    wend = (char*)memchr(wstart, ' ', lend - wstart);
    if(wend || lend - wstart != 8 || memcmp(wstart, "HTTP/1.1", 8) != 0) {
        err = EPROTO; goto err2;}
    int hasupgrade = 0;
    int hasconnection = 0;
    int haskey = 0;
    int hassubprotocol = 0;
    const char *subprotocol = NULL;
    size_t subprotocolsz = 0;
    struct wsock_sha1 sha1;
    while(1) {
        sz = wsock_getline(as, buf, sizeof(buf), deadline);
        if(sz < 0) {err = errno; goto err2;}
        if(sz == 0)
            break;
        lend = buf + sz;
        char *nstart = buf;
        char *nend = (char*)memchr(buf, ' ', lend - nstart);
        if(!nend || nend - nstart < 1 || nend[-1] != ':') {
            err = EPROTO; goto err2;}
        size_t nsz = nend - nstart - 1;
        char *vstart = nend + 1;
        char *vend = (char*)memchr(vstart, ' ', lend - vstart);
        if(vend) {err = EPROTO; goto err2;}
        size_t vsz = lend - vstart;
        if(nsz == 7 && memcmp(nstart, "Upgrade", 7) == 0) {
            if(hasupgrade || vsz != 9 || memcmp(vstart, "websocket", 9) != 0) {
                err = EPROTO; goto err2;}
            hasupgrade = 1;
            continue;
        }
        if(nsz == 10 && memcmp(nstart, "Connection", 10) == 0) {
            if(hasconnection || vsz != 7 || memcmp(vstart, "Upgrade", 7) != 0) {
                err = EPROTO; goto err2;}
            hasconnection = 1;
            continue;
        }
        if(nsz == 17 && memcmp(nstart, "Sec-WebSocket-Key", 17) == 0) {
            if(haskey) {err = EPROTO; goto err2;}
            wsock_sha1_init(&sha1);
            int i;
            for(i = 0; i != vsz; ++i)
                wsock_sha1_hashbyte(&sha1, vstart[i]);
            const char *uuid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
            for(i = 0; i != 36; ++i)
                wsock_sha1_hashbyte(&sha1, uuid[i]);
            haskey = 1;
            continue;
        }
        if(nsz == 22 && memcmp(nstart, "Sec-WebSocket-Protocol", 22) == 0) {
            /* TODO: RFC6455, section 11.3.4 allows for multiple instances of
               this field. */
            if(hassubprotocol) {err = EPROTO; goto err2;}
            const char *available = wsock_str_get(&s->subprotocol);
            if(available) {
                subprotocol = wsock_hassubprotocol(available, vstart, vsz,
                    &subprotocolsz);
                if(!subprotocol) {err = EPROTO; goto err2;}
            }
            else {
                subprotocol = vstart;
                subprotocolsz = vsz;
            }
            hassubprotocol = 1;
            wsock_str_init(&as->subprotocol, subprotocol, subprotocolsz);
            continue;
        }
    }
    if(!hasupgrade || !hasconnection || !haskey) {err = EPROTO; goto err2;}

    /* If the subprotocol was not specified by the client, we still want to
       use one of the suerver-supported protocols locally. */
    if(!subprotocol) {
        const char *available = wsock_str_get(&s->subprotocol);
        if(available) {
            size_t asz = 0;
            while(available[asz] != 0 && available[asz] != ',')
                ++asz;
            wsock_str_init(&as->subprotocol, available, asz);
        }
    }

    /* Send reply. */
    const char *lit1 =
        "HTTP/1.1 101 Switching Protocols\r\n"
        "Upgrade: websocket\r\n"
        "Connection: Upgrade\r\n"
        "Sec-WebSocket-Accept: ";
    tcpsend(as->u, lit1, strlen(lit1), deadline);
    if(errno != 0) {err = errno; goto err2;}
    char key[32];
    wsock_sha1_result(&sha1);
    sz = wsock_base64_encode(wsock_sha1_result(&sha1), 20, key, sizeof(key));
    assert(sz > 0);
    tcpsend(as->u, key, sz, deadline);
    if(errno != 0) {err = errno; goto err2;}
    if(hassubprotocol) {
        tcpsend(as->u, "\r\nSec-WebSocket-Protocol: ", 26, deadline);
        if(errno != 0) {err = errno; goto err2;}
        tcpsend(as->u, subprotocol, subprotocolsz, deadline);
        if(errno != 0) {err = errno; goto err2;}
    }
    tcpsend(as->u, "\r\n\r\n", 4, deadline);
    if(errno != 0) {err = errno; goto err2;}
    tcpflush(as->u, deadline);
    if(errno != 0) {err = errno; goto err2;}

    return as;

err2:
    tcpclose(as->u);
err1:
    free(as);
err0:
    errno = err;
    return NULL;
}
Example #22
0
wsock wsockconnect(ipaddr addr, const char *subprotocol, const char *url,
      int64_t deadline) {
    /* Check the arguments. */
    if(!wsock_checkstring(url))
        return NULL;
    if(subprotocol) {
        if(!wsock_checkstring(subprotocol))
        return NULL;
    }

    /* Open TCP connection. */
    int err = 0;
    struct wsock *s = (struct wsock*)malloc(sizeof(struct wsock));
    if(!s) {err = ENOMEM; goto err0;}
    s->flags = WSOCK_CLIENT;
    s->u = tcpconnect(addr, deadline);
    if(errno != 0) {err = errno; goto err1;}
    wsock_str_init(&s->url, url, strlen(url));
    wsock_str_init(&s->subprotocol, NULL, 0);

    /* Send request. */
    tcpsend(s->u, "GET ", 4, deadline);
    if(errno != 0) {err = errno; goto err2;}
    tcpsend(s->u, url, strlen(url), deadline);
    if(errno != 0) {err = errno; goto err2;}
    const char *lit1 =
        " HTTP/1.1\r\n"
        "Upgrade: websocket\r\n"
        "Connection: Upgrade\r\n"
        "Sec-WebSocket-Key: ";
    tcpsend(s->u, lit1, strlen(lit1), deadline);
    if(errno != 0) {err = errno; goto err2;}
    uint8_t nonce[16];
    int i;
    for(i = 0; i != 8; ++i)
        ((uint16_t*)  nonce)[i] = wsock_random() & 0xffff;
    char swsk[32];
    int swsk_len = wsock_base64_encode(nonce, 16, swsk, sizeof(swsk));
    assert(swsk_len > 0);
    tcpsend(s->u, swsk, swsk_len, deadline);
    if(errno != 0) {err = errno; goto err2;}
    if(subprotocol) {
        tcpsend(s->u, "\r\nSec-WebSocket-Protocol: ", 26, deadline);
        if(errno != 0) {err = errno; goto err2;}
        tcpsend(s->u, subprotocol, strlen(subprotocol), deadline);
        if(errno != 0) {err = errno; goto err2;}
    }
    tcpsend(s->u, "\r\n\r\n", 4, deadline);
    if(errno != 0) {err = errno; goto err2;}
    tcpflush(s->u, deadline);
    if(errno != 0) {err = errno; goto err2;}

    /* Parse reply. */
    char buf[256];
    size_t sz = wsock_getline(s, buf, sizeof(buf), deadline);
    if(sz < 0) {err = errno; goto err2;}
    char *lend = buf + sz;
    char *wstart = buf;
    char *wend = (char*)memchr(buf, ' ', lend - wstart);
    if(!wend || wend - wstart != 8 || memcmp(wstart, "HTTP/1.1", 8) != 0) {
        err = EPROTO; goto err2;}
    wstart = wend + 1;
    wend = (char*)memchr(wstart, ' ', lend - wstart);
    if(!wend || wend - wstart != 3 || memcmp(wstart, "101", 3) != 0) {
        err = EPROTO; goto err2;}
    int hasupgrade = 0;
    int hasconnection = 0;
    int haskey = 0;
    int hassubprotocol = 0;
    while(1) {
        sz = wsock_getline(s, buf, sizeof(buf), deadline);
        if(sz < 0) {err = errno; goto err2;}
        if(sz == 0)
            break;
        lend = buf + sz;
        char *nstart = buf;
        char *nend = (char*)memchr(buf, ' ', lend - nstart);
        if(!nend || nend - nstart < 1 || nend[-1] != ':') {
            err = EPROTO; goto err2;}
        size_t nsz = nend - nstart - 1;
        char *vstart = nend + 1;
        char *vend = (char*)memchr(vstart, ' ', lend - vstart);
        if(vend) {err = EPROTO; goto err2;}
        size_t vsz = lend - vstart;
        if(nsz == 7 && memcmp(nstart, "Upgrade", 7) == 0) {
            if(hasupgrade || vsz != 9 || memcmp(vstart, "websocket", 9) != 0) {
                err = EPROTO; goto err2;}
            hasupgrade = 1;
            continue;
        }
        if(nsz == 10 && memcmp(nstart, "Connection", 10) == 0) {
            if(hasconnection || vsz != 7 || memcmp(vstart, "Upgrade", 7) != 0) {
                err = EPROTO; goto err2;}
            hasconnection = 1;
            continue;
        }
        if(nsz == 20 && memcmp(nstart, "Sec-WebSocket-Accept", 20) == 0) {
            if(haskey) {err = EPROTO; goto err2;}
            /* TODO */
            haskey = 1;
            continue;
        }
        if(nsz == 22 && memcmp(nstart, "Sec-WebSocket-Protocol", 22) == 0) {
            if(hassubprotocol) {err = EPROTO; goto err2;}
            for(i = 0; i != vsz; ++i)
                if(vstart[i] == ',') {err = EPROTO; goto err2;}
            if(!wsock_hassubprotocol(subprotocol, vstart, vsz, NULL)) {
                err = EPROTO; goto err2;}
            wsock_str_init(&s->subprotocol, vstart, vsz);
            hassubprotocol = 1;
            continue;
        }
    }
    if(!hasupgrade || !hasconnection || !haskey) {err = EPROTO; goto err2;}

    return s;

err2:
    tcpclose(s->u);
err1:
    free(s);
err0:
    errno = err;
    return NULL;
}
Example #23
0
size_t wsockrecv(wsock s, void *msg, size_t len, int64_t deadline) {
    if(s->flags & WSOCK_LISTENING) {errno = EOPNOTSUPP; return 0;}
    if(s->flags & WSOCK_BROKEN) {errno = ECONNABORTED; return 0;}
    size_t res = 0;
    while(1) {
        uint8_t hdr1[2];
        tcprecv(s->u, hdr1, 2, deadline);
        if(errno != 0) {s->flags |= WSOCK_BROKEN; return 0;}
        if(hdr1[0] & 0x70) {
            s->flags &= WSOCK_BROKEN; errno = EPROTO; return 0;}
        int opcode = hdr1[0] & 0x0f;
        if(opcode == 8) {
            if(!(s->flags & WSOCK_DONE)) {
                /* TODO: Close frames from client should be masked. */
                tcpsend(s->u, "\x88\x00", 2, deadline);
                tcpflush(s->u, deadline);
                s->flags |= (WSOCK_BROKEN & WSOCK_DONE);
            }
            errno = ECONNRESET;
            return 0;
        }
        if(opcode == 9) {
            /* TODO: Account for pings and pongs with payload. */
            if(!(s->flags & WSOCK_DONE)) {
                tcpsend(s->u, "\x8A\x00", 2, deadline);
                if(errno != 0) {s->flags &= WSOCK_BROKEN; return 0;}
                tcpflush(s->u, deadline);
                if(errno != 0) {s->flags &= WSOCK_BROKEN; return 0;}
            }
            continue;
        }
        if(opcode == 10) {
            /* TODO: Account for pings and pongs with payload. */
            /* TODO: Do we want to make exiting the function here optional? */
            errno = EAGAIN;
            return 0;
        }
        if(!!(s->flags & WSOCK_CLIENT) ^ !(hdr1[1] & 0x80)) {
            s->flags &= WSOCK_BROKEN; errno = EPROTO; return 0;}
        size_t sz = hdr1[1] & 0x7f;
        if(sz == 126) {
            uint8_t hdr2[2];
            tcprecv(s->u, hdr2, 2, deadline);
            if(errno != 0) {s->flags |= WSOCK_BROKEN; return 0;}
            sz = wsock_gets(hdr2);
        }
        else if(sz == 127) {
            uint8_t hdr2[8];
            tcprecv(s->u, hdr2, 8, deadline);
            if(errno != 0) {s->flags |= WSOCK_BROKEN; return 0;}
            sz = wsock_getll(hdr2);
        }
        uint8_t mask[4];
        if(!(s->flags & WSOCK_CLIENT)) {
            tcprecv(s->u, mask, 4, deadline);
            if(errno != 0) {s->flags |= WSOCK_BROKEN; return 0;}
        }
        size_t toread = sz < len ? sz : len;
        if(toread > 0) {
            tcprecv(s->u, msg, toread, deadline);
            if(errno != 0) {s->flags |= WSOCK_BROKEN; return 0;}
        }
        if(!(s->flags & WSOCK_CLIENT)) {
            size_t i;
            for(i = 0; i != toread; ++i)
                ((uint8_t*)msg)[i] ^= mask[i % 4];
        }
        if(sz > toread) {
            tcprecv(s->u, NULL, sz - toread, deadline);
            if(errno != 0) {s->flags |= WSOCK_BROKEN; return 0;}
        }
        res += sz;
        if(hdr1[0] & 0x80)
            break;
        msg = ((uint8_t*)msg) + sz;
        len -= sz;
    }
    return res;
}
Example #24
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(http_req_process, ev, data)
{
    static struct etimer httptimeout;
	SOCKETMSG msg;

    PROCESS_BEGIN();

    while(1)
    {
		//wait for TCP connected or uip_timeout.
		PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_MSG || ev == PROCESS_EVENT_TIMER || ev == PROCESS_EVENT_EXIT);
        if(ev == PROCESS_EVENT_MSG)
        {
    		msg = *(SOCKETMSG *)data;
    		if(msg.status == SOCKET_CONNECTED)
    		{
    		    //send out the http request.
    		    if(httpreqdata.cmdlen)
                    tcpsend(httpreqdata.httpsock, httpreqdata.httpcmd, httpreqdata.cmdlen);
    		}
    		else if(msg.status == SOCKET_SENDACK)
    		{
    		    //set timeot for http response.
    		    etimer_set(&httptimeout, 10 * CLOCK_CONF_SECOND);
    		}
    		else if(msg.status == SOCKET_NEWDATA)
    		{
    			//Get http response, parse response and close socket.
    			etimer_stop(&httptimeout);
                httpreqdata.rsplen = tcprecv(httpreqdata.httpsock, httpreqdata.httprsp, HTTPRSP_MAX);
                tcpclose(httpreqdata.httpsock);
                httpreqdata.httpsock = -1;
                httpreqdata.httpstatus = HTTP_IDLE;
                if(httpreqdata.rsplen > 0 && httpreqdata.callbackfn)
                {
                    httpreqdata.httprsp[httpreqdata.rsplen] = 0;
                    httprsp_parse(httpreqdata.httprsp, httpreqdata.rsplen);
                }
    		}
    		else if(msg.status == SOCKET_CLOSED)
    		{
    			//socket closed, if it is unnormal case, notify upper layer.
    			if(httpreqdata.httpstatus != HTTP_IDLE)
                {
                    if(httpreqdata.callbackfn)
                    {
                        httpmsg.msgtype = HTTPREQ_CONN_ERROR;
                        httpmsg.rsp = NULL;
                        httpreqdata.callbackfn(&httpmsg);
                    }
                    httpreqdata.httpsock = -1;
                    httpreqdata.httpstatus = HTTP_IDLE;
                }
    		}
        }
        else if(ev == PROCESS_EVENT_TIMER)
        {
            //http response timeout, close socket and notify upper layer.
            tcpclose(httpreqdata.httpsock);
            httpreqdata.httpsock = -1;
            httpreqdata.httpstatus = HTTP_IDLE;
            if(httpreqdata.callbackfn)
            {
                httpmsg.msgtype = HTTPREQ_RSP_TIMEOUT;
                httpmsg.rsp = NULL;
                httpreqdata.callbackfn(&httpmsg);
            }
        }
        else if(ev == PROCESS_EVENT_EXIT)
        {
            break;
        }
    }

    PROCESS_END();
}