int tcpconnect(const ipaddr *addr, int64_t deadline) {
    int err;
    /* Open a socket. */
    int s = socket(ipfamily(addr), SOCK_STREAM, 0);
    if(dill_slow(s < 0)) return -1;
    tcptune(s);
    /* Connect to the remote endpoint. */
    int rc = dsconnect(s, ipsockaddr(addr), iplen(addr), deadline);
    if(dill_slow(rc < 0)) return -1;
    /* Create the object. */
    struct tcpconn *conn = tcpconn_create();
    if(dill_slow(!conn)) {err = errno; goto error1;}
    conn->fd = s;
    conn->addr = *addr;
    /* Bind the object to a sock handle. */
    int bs = bsock(tcpconn_type, conn, &tcpconn_vfptrs);
    if(dill_slow(bs < 0)) {err = errno; goto error2;}
    return bs;
error2:
    tcpconn_destroy(conn);
error1:
    rc = dsclose(s);
    dill_assert(rc == 0);
    errno = err;
    return -1;
}
Example #2
0
char * get_packet(int fd) {
    size_t cnt = 0, len = 0;
    ssize_t rc = 0;
    unsigned char * pkt = malloc(20 + 4);

    if(!pkt) {
        printf("Unable to malloc() space for next packet!\n");
        return NULL;
    }


    // 4 bytes, TUN info + 20 bytes, the size of an IP header
    while (cnt < (20 + 4))
    {
	if ((rc = read(fd, pkt+cnt, 24)) <= 0 )
	{
        	if (rc < 0)
		{
                    if (errno == EINTR)
			continue;
                    printf("Socket #%d: Reading IP hdr: %s.", fd, strerror(errno));
                } else
		    printf("Socket #%d: Read %d bytes, expected 24 (hdr).", fd, cnt);

                free(pkt);
                return NULL;
        }
        cnt += rc;
    } 
    len = iplen(pkt);

    return pkt;
}
Example #3
0
int handle_s_p2( clidata_t *client, char *hdrs ) {
    int gotten=0;
    int expected = get_content_length(hdrs);
    char *pkt;
    int cnt=0;
    queue_t *recvq = client->recvq;
    int chan1 = client->chan1;

    if( !expected ) {
        lprintf(log, WARN, 
                "Client sent no Content-Length. Dropping.");
        return -1;
    }

    while( gotten < expected ) {
        if( (pkt=get_packet(chan1)) == NULL ) {
            lprintf(log, WARN, 
                    "get_packet() failed. Dropping client.");
            fdprintf(chan1, RESPONSE_500_ERR);
            return -1;
        }
        cnt++;
        gotten += iplen(pkt);
        dprintf(log, DEBUG, "got %d of %d bytes from client",
                gotten, expected);
        if( (q_add(recvq, pkt, Q_WAIT, iplen(pkt))) == -1 ) {
            lprintf(log, WARN, "q_add() failed. Dropping client.");
            fdprintf(chan1, RESPONSE_500_ERR);
            return -1;
        }
    }
    lprintf(log, INFO, "Got  %d bytes in %d pkts",
            gotten, cnt);

    fdprintf(chan1, RESPONSE_204);
    return 0;

}
int tcplisten(const ipaddr *addr, int backlog) {
    int err;
    if(dill_slow(backlog < 0)) {errno = EINVAL; return -1;}
    /* Open listening socket. */
    int s = socket(ipfamily(addr), SOCK_STREAM, 0);
    if(dill_slow(s < 0)) return -1;
    tcptune(s);
    /* Start listening. */
    int rc = bind(s, ipsockaddr(addr), iplen(addr));
    if(dill_slow(rc != 0)) return -1;
    rc = listen(s, backlog);
    if(dill_slow(rc != 0)) return -1;
    /* If the user requested an ephemeral port,
       retrieve the port number assigned by the OS now. */
    int port = ipport(addr);
    if(port == 0) {
        ipaddr baddr;
        socklen_t len = sizeof(ipaddr);
        rc = getsockname(s, (struct sockaddr*)&baddr, &len);
        if(dill_slow(rc < 0)) {err = errno; goto error1;}
        port = ipport(&baddr);
    }
    /* Create the object. */
    struct tcplistener *lst = malloc(sizeof(struct tcplistener));
    if(dill_slow(!lst)) {errno = ENOMEM; goto error1;}
    lst->fd = s;
    lst->port = port;
    /* Bind the object to a handle. */
    int h = handle(tcplistener_type, lst, &tcplistener_vfptrs);
    if(dill_slow(h < 0)) {err = errno; goto error2;}
    return h;
error2:
    free(lst);
error1:
    rc = dsclose(s);
    dill_assert(rc == 0);
    errno = err;
    return -1;
}
Example #5
0
int handle_r_p2( clidata_t *client, char *hdrs ) {
    int expected = get_content_length(hdrs);
    queue_t *sendq = client->sendq;
    int chan2 = client->chan2;
    struct timespec ts;
    char *body;
    int sex;
    char *pkt;

    if( !expected ) {
        lprintf(log, WARN, 
                "Client sent no Content-Length. Dropping.");
        goto cleanup1;
    }

    if( (body=getbody(chan2, hdrs, &expected)) == NULL ) {
        lprintf(log, WARN, "getbody() failed. Dropping client.");
        goto cleanup1;
    }

    if( (sex=strtol(body, NULL, 0)) == 0 ) {
        lprintf(log, WARN, "Client sent invalid seconds spec.");
        fdprintf(chan2, RESPONSE_400);
        goto cleanup2;
    }

    ts.tv_nsec = 0;
    ts.tv_sec = sex;

    dprintf(log, DEBUG, "waiting up to %d seconds.", sex);

    if( q_timedwait(sendq, &ts) ) {
        int sent=0, total, cnt=0;

        dprintf(log, DEBUG, "returned from wait, with data");
        total = sendq->totsize;
        fdprintf(chan2, RESPONSE_200_NOBODY, sendq->totsize);

        while( sent < total ) {
            if( (pkt=q_remove(sendq, 0, NULL)) == NULL ) {
                lprintf(log, WARN, "q_remove failed!");
                goto cleanup2;
            }
            if( write(chan2, pkt, iplen(pkt)) < 0 ) {
                lprintf(log, INFO, "send failed: %s",
                        strerror(errno));
                free(pkt);
                goto cleanup2;
            }
            cnt++;
            sent += iplen(pkt);
            free(pkt);
        }
        lprintf(log, INFO, "Sent %d bytes in %d pkts",
                sent, cnt);
    } else {
        dprintf(log, DEBUG, "returned from wait, with NO data");
        if( client->chan2 != -1 ) fdprintf(chan2, RESPONSE_204);
    }
    
    return 0;


cleanup2:
    free(body);
cleanup1:
    return -1;

}