Beispiel #1
0
void put_handle (struct shim_handle * hdl)
{
    int ref_count = REF_DEC(hdl->ref_count);

#ifdef DEBUG_REF
    debug("put handle %p(%s) (ref_count = %d)\n", hdl, __handle_name(hdl),
          ref_count);
#endif

    if (!ref_count) {
        if (hdl->fs && hdl->fs->fs_ops &&
            hdl->fs->fs_ops->hput)
            hdl->fs->fs_ops->hput(hdl);

        qstrfree(&hdl->path);
        qstrfree(&hdl->uri);

        if (hdl->pal_handle)
            DkObjectClose(hdl->pal_handle);

        if (hdl->dentry)
            put_dentry(hdl->dentry);

        if (hdl->fs)
            put_mount(hdl->fs);

        destroy_handle(hdl);
    }
}
Beispiel #2
0
int main (int argc, char ** argv, char ** envp)
{
    pal_printf("Enter Main Thread\n");

    PAL_HANDLE out = DkStreamOpen(file_uri, PAL_ACCESS_RDWR,
                                  PAL_SHARE_OWNER_W,
                                  PAL_CREAT_TRY, 0);

    if (out == NULL) {
        pal_printf("DkStreamOpen failed\n");
        return -1;
    }

    str[0] = 'H';
    str[1] = 'e';
    str[2] = 'l';
    str[3] = 'l';
    str[4] = 'o';
    str[5] = ' ';
    str[6] = 'W';
    str[7] = 'o';
    str[8] = 'r';
    str[9] = 'l';
    str[10] = 'd';
    str[11] = 0;

    int bytes = DkStreamWrite(out, 0, 11, str, NULL);

    if (!bytes) {
        pal_printf("DkStreamWrite failed\n");
        return -1;
    }

    DkObjectClose(out);

    PAL_HANDLE in = DkStreamOpen(file_uri, PAL_ACCESS_RDONLY, 0, 0, 0);

    bytes = DkStreamRead(in, 0, 20, str, NULL, 0);

    if (!bytes) {
        pal_printf("DkStreamRead failed\n");
        return -1;
    }

    pal_printf("%s\n", str);

    DkStreamDelete(in, 0);

    PAL_HANDLE del = DkStreamOpen(file_uri, PAL_ACCESS_RDWR, 0, 0, 0);

    if (del) {
        pal_printf("DkStreamDelete failed\n");
        return -1;
    }

    pal_printf("Leave Main Thread\n");
    return 0;
}
Beispiel #3
0
int create_pipes (IDTYPE * pipeid, PAL_HANDLE * srv, PAL_HANDLE * cli,
                  struct shim_qstr * qstr, int flags)
{
    PAL_HANDLE hdl0 = NULL, hdl1 = NULL, hdl2 = NULL;
    int ret = 0;
    char * uri = __alloca(PIPE_URI_SIZE);

    if ((ret = create_pipe(pipeid, uri, PIPE_URI_SIZE, &hdl0,
                           qstr)) < 0) {
        debug("pipe creation failure\n");
        return ret;
    }

    if (!(hdl2 = DkStreamOpen(uri, 0, 0, 0,
                              flags & O_NONBLOCK))) {
        ret = -PAL_ERRNO;
        debug("pipe connection failure\n");
        goto err;
    }

    if (!(hdl1 = DkStreamWaitForClient(hdl0))) {
        ret = -PAL_ERRNO;
        debug("pipe acception failure\n");
        goto err;
    }

    DkStreamDelete(hdl0, 0);
    DkObjectClose(hdl0);
    *srv = hdl1;
    *cli = hdl2;
    return 0;
err:
    if (hdl1)
        DkObjectClose(hdl1);
    if (hdl2)
        DkObjectClose(hdl2);
    DkStreamDelete(hdl0, 0);
    DkObjectClose(hdl0);
    return ret;
}
static void __put_ipc_port (struct shim_ipc_port * pobj)
{
    int ref_count = REF_DEC(pobj->ref_count);

#ifdef DEBUG_REF
    debug("put ipc port %p (handle %p, ref_count = %d)\n", pobj,
          pobj->pal_handle, ref_count);
#endif

    if (!ref_count) {
        if (pobj->pal_handle) {
            DkObjectClose(pobj->pal_handle);
            pobj->pal_handle = NULL;
        }

        free_mem_obj_to_mgr(port_mgr, pobj);
    }
}
Beispiel #5
0
int main (int argc, char ** argv)
{
    int nsend = 5 , i;
    PAL_HANDLE handles[nsend];

    if (argc == 1)  /* parent */
    {
        pal_printf("Parent: Executing the program\n");

        const char *args[3] = { "HandleSend", "child", NULL };
        char * data = "Hello World";
        char content[20];
        char uri[80];
        PAL_HANDLE child;
        int bytes;

        pal_printf("Parent: Creating handles\n");

        // Sending pipe handle
        handles[0] = DkStreamOpen("pipe.srv:012", PAL_ACCESS_RDWR,
                                  0, PAL_CREATE_TRY, 0);
        if (!handles[0]) {
            pal_printf("Parent: DkStreamOpen for pipe failed\n");
            goto out;
        }

        // Sending pipe handle
        handles[1] = DkStreamOpen("udp:127.0.0.1:8000", PAL_ACCESS_RDWR,
                                  0, PAL_CREATE_TRY, 0);
        if (!handles[1]) {
            pal_printf("Parent: DkStreamOpen for socket failed\n");
            goto out;
        }

        for (i = 2 ; i < nsend; i++) {
            snprintf(uri, 80, "file:test_file_%d", i - 2);

            handles[i] = DkStreamOpen(uri, PAL_ACCESS_RDWR, 0600,
                                      PAL_CREATE_TRY, 0);
            if (!handles[i]) {
                pal_printf("Parent: DkStreamOpen failed\n");
                goto out;
            }

            DkStreamSetLength(handles[i], 0);
        }

        for (i = 0 ; i < nsend ; i++) {
            /* do some write */
            snprintf(content, sizeof(content), "%s%d", data, i);

            bytes = DkStreamWrite(handles[i], 0, sizeof(content), content,
                                  NULL);
            if (!bytes) {
                pal_printf("Parent: DKStreamWrite failed\n");
                goto out;
            }

            DkStreamFlush(handles[i]);
        }

        pal_printf("Parent: Forking child\n");
        child = DkProcessCreate ("file:HandleSend", args);

        if (!child) {
            pal_printf("Parent: Failed creating process\n");
            DkProcessExit(1);
        }

        for (i = 0 ; i < nsend ; i++) {
            pal_printf("Parent: Sending Handle %d\n", i);

            if (!DkSendHandle(child, handles[i])) {
                pal_printf("Send handle failed\n");
                goto out;
            }

            DkObjectClose(handles[i]);
        }

        pal_printf("Parent: Finished execution\n");

        DkObjectClose(child);
    }
    else            /* child */
    {
        PAL_HANDLE parent = pal_control.parent_process;

        for (i = 0 ; i < nsend ; i++) {
            pal_printf("Child: Receiving Handle %d\n", i);
            handles[i] = DkReceiveHandle(parent);

            if (!handles[i]) {
                pal_printf("Child: Failed receiving handle\n");
                DkProcessExit(1);
            }
        }

        pal_printf("Child: Reading the handles\n");
        for (i = 0 ; i < nsend ; i++) {
            /* do some read */
            pal_printf("Child: Handle %d Type ", i);
            char data[20];

            switch(PAL_GET_TYPE(handles[i])) {
                case pal_type_file:
                    if ((DkStreamRead(handles[i], 0, 20, data, NULL, 0)))
                        pal_printf("File Data: %s\n", data);
                    else
                        pal_printf("Couldn't read\n");
                    break;
                case pal_type_pipesrv:
                    pal_printf("Pipe\n");
                    break;
                case pal_type_udp:
                    pal_printf("Udp\n");
                    break;
                default:
                    pal_printf("Unknown\n");
            }

            DkObjectClose(handles[i]);
        }

        pal_printf("Child: Finished execution\n\n");

        DkObjectClose(parent);
    }

out:
    for (i = 0 ; i < nsend ; i++)
        DkObjectClose(handles[i]);

    return 0;
}
Beispiel #6
0
int main (int argc, char ** argv)
{
    if (argc < 2) {
        pal_printf("specify the port to open\n");
        return 0;
    }

    char uri[60];
    snprintf(uri, 60, "tcp.srv:127.0.0.1:%s", argv[1]);

    PAL_HANDLE srv = DkStreamOpen(uri, PAL_ACCESS_RDWR, 0,
                                  PAL_CREAT_TRY, 0);

    if (srv == NULL) {
        pal_printf("DkStreamOpen failed\n");
        return -1;
    }

    void * buffer = (void *) DkVirtualMemoryAlloc(NULL, 4096, 0,
                                                  PAL_PROT_READ|PAL_PROT_WRITE);
    if (!buffer) {
        pal_printf("DkVirtualMemoryAlloc failed\n");
        return -1;
    }

    PAL_HANDLE hdls[8];
    int nhdls = 1, i;
    hdls[0] = srv;

    while(1) {
        PAL_HANDLE hdl = DkObjectsWaitAny(nhdls, hdls, NO_TIMEOUT);

        if (!hdl)
            continue;

        if (hdl == srv) {
            hdl = DkStreamWaitForClient(srv);

            if (!hdl)
                continue;

            if (nhdls >= 8) {
                pal_printf("[ ] connection rejected\n");
                DkObjectClose(hdl);
                continue;
            }

            pal_printf("[%d] receive new connection\n", nhdls);
            hdls[nhdls++] = hdl;
            continue;
        }

        int cnt = 0;
        for (i = 0 ; i < nhdls ; i++)
            if (hdls[i] == hdl)
                cnt = i;

        int bytes = DkStreamRead(hdl, 0, 4096, buffer, NULL, 0);

        if (bytes == 0) {
            DkObjectClose(hdls[cnt]);
            if (cnt != nhdls - 1)
                hdls[cnt] = hdls[nhdls - 1];
            nhdls--;
            continue;
        }

        ((char *) buffer)[bytes] = 0;

        pal_printf("[%d] %s", cnt, (char *) buffer);
    }
    return 0;
}
Beispiel #7
0
int main(int argc, char ** argv)
{
    char * name = "parent";

    if (argc == 1) {
        const char * args[3];
        char uri[20], uri2[20];

        snprintf(uri2, 20, "file:%s", argv[0]);

        args[0] = "Ipc";
        args[1] = uri;
        args[2] = NULL;

        void * mem = (void *) DkVirtualMemoryAlloc(NULL,
                                                   pal_control.alloc_align, 0,
                                                   PAL_PROT_READ|PAL_PROT_WRITE);

        pal_printf("mem = %p\n", mem);
        snprintf((char *) mem, 4096, "Hello World");

        PAL_NUM key = 0;

        PAL_HANDLE chdl = DkCreatePhysicalMemoryChannel(&key);

        if (chdl == NULL) {
            pal_printf ("(parent) DkCreatePhysicalMemoryChannel Failed,"
                         " Make sure gipc module is loaded\n");
            return 0;
        }

        snprintf(uri, 20, "gipc:%lld", key);

        PAL_HANDLE phdl = DkProcessCreate(uri2, 0, args);

        if (phdl == NULL)
            pal_printf ("ProcessCreate Failed\n");

        PAL_PTR addr = (PAL_PTR) mem;
        PAL_NUM size = pal_control.alloc_align;
        DkPhysicalMemoryCommit(chdl, 1, &addr, &size, 0);
        DkObjectClose(chdl);

        char x;
        int rv = DkStreamRead(phdl, 0, 1, &x, NULL, 0);
        if (rv != 1) {
            pal_printf("Failed to get exit signal from child, %d\n", rv);
            return -1;
        }
    }
    else {
        name = argv[1];

        PAL_HANDLE chdl = DkStreamOpen(name, 0, 0, 0, 0);

        if (chdl == NULL) {
            pal_printf("(child) StreamOpen Failed\n");
            return 0;
        }

        PAL_PTR addr = NULL;
        PAL_NUM size = pal_control.alloc_align;
        PAL_FLG prot = PAL_PROT_READ|PAL_PROT_WRITE;

        int len = DkPhysicalMemoryMap (chdl, 1, &addr, &size, &prot);

        if (!len) {
            pal_printf("PhysicalMemoryMap Failed\n");
            return 0;
        }

        pal_printf("(child) mem = %p\n", addr);
        pal_printf("(child) receive string: %s\n", (char *) addr);

        DkStreamDelete(chdl, 0);
        DkObjectClose(chdl);

        // Write a byte to the parent
        int rv = DkStreamWrite(pal_control.parent_process, 0, 1, "z", NULL);
        if (rv < 0) {
            pal_printf("Failed to write an exit byte\n");
            return -1;
        }
    }

    pal_printf("Enter Main Thread (%s)\n", name);

    DkThreadDelayExecution (3000);

    pal_printf("Leave Main Thread\n");
    return 0;
}
Beispiel #8
0
static int __load_msg_persist (struct shim_msg_handle * msgq, bool readmsg)
{
    int ret = 0;

    char fileuri[20];
    snprintf(fileuri, 20, "file:msgq.%08x", msgq->msqid);

    PAL_HANDLE file = DkStreamOpen(fileuri, PAL_ACCESS_RDONLY, 0, 0, 0);

    if (!file)
        return -EIDRM;

    struct msg_handle_backup mback;

    int bytes = DkStreamRead(file, 0, sizeof(struct msg_handle_backup),
                             &mback, NULL, 0);

    if (bytes < sizeof(struct msg_handle_backup)) {
        ret = bytes ? -EFAULT : -PAL_ERRNO;
        goto out;
    }

    msgq->perm = mback.perm;

    if (!readmsg || !mback.nmsgs)
        goto done;

    int expected_size = sizeof(struct msg_handle_backup) +
                        sizeof(struct msg_backup) * mback.nmsgs +
                        mback.currentsize;

    void * mem = (void *) DkStreamMap(file, NULL, PAL_PROT_READ, 0,
                                      ALIGN_UP(expected_size));

    if (!mem) {
        ret = -PAL_ERRNO;
        goto out;
    }

    mem += sizeof(struct msg_handle_backup);

    struct msg_type * mtype = NULL;
    for (int i = 0 ; i < mback.nmsgs ; i++) {
        struct msg_backup * m = mem;
        mem += sizeof(struct msg_backup) + m->size;

        debug("load msg: type=%d, size=%d\n", m->type, m->size);

        if (!mtype || mtype->type != m->type)
            mtype = __add_msg_type(m->type, &msgq->types, &msgq->ntypes,
                                   &msgq->maxtypes);

        if ((ret = __store_msg_qobjs(msgq, mtype, m->size, m->data)) < 0)
            goto out;
    };

    DkStreamUnmap(mem, ALIGN_UP(expected_size));

done:
    DkStreamDelete(file, 0);
    ret = 0;
    goto out;

out:
    DkObjectClose(file);
    return ret;
}
Beispiel #9
0
static int __store_msg_persist (struct shim_msg_handle * msgq)
{
    int ret = 0;

   if (msgq->deleted)
        goto out;

    debug("store msgq %d to persistent store\n", msgq->msqid);

    char fileuri[20];
    snprintf(fileuri, 20, "file:msgq.%08x", msgq->msqid);

    PAL_HANDLE file = DkStreamOpen(fileuri, PAL_ACCESS_RDWR, 0600,
                                   PAL_CREAT_TRY, 0);
    if (!file) {
        ret = -PAL_ERRNO;
        goto out;
    }

    int expected_size = sizeof(struct msg_handle_backup) +
                        sizeof(struct msg_backup) * msgq->nmsgs +
                        msgq->currentsize;

    if (DkStreamSetLength(file, expected_size) != expected_size)
        goto err_file;

    void * mem = (void *) DkStreamMap(file, NULL,
                                      PAL_PROT_READ|PAL_PROT_WRITE,
                                      0, ALIGN_UP(expected_size));
    if (!mem) {
        ret = -EFAULT;
        goto err_file;
    }

    struct msg_handle_backup * mback = mem;
    mem += sizeof(struct msg_handle_backup);

    mback->perm        = msgq->perm;
    mback->nmsgs       = msgq->nmsgs;
    mback->currentsize = msgq->currentsize;

    struct msg_type * mtype;
    for (mtype = msgq->types ; mtype < &msgq->types[msgq->ntypes] ;
         mtype++) {
        while (mtype->msgs) {
            struct msg_backup * msg = mem;
            mem += sizeof(struct msg_backup) + mtype->msgs->size;

            msg->type = mtype->type;
            msg->size = mtype->msgs->size;
            __load_msg_qobjs(msgq, mtype, mtype->msgs, msg->data);
        }

        mtype->msgs = mtype->msg_tail = NULL;
    }

    DkStreamUnmap(mem, ALIGN_UP(expected_size));

    if (msgq->owned)
        for (mtype = msgq->types ; mtype < &msgq->types[msgq->ntypes] ;
             mtype++) {
            struct msg_req * req = mtype->reqs;
            mtype->reqs = mtype->req_tail = NULL;
            while (req) {
                struct sysv_client * c = &req->dest;
                struct msg_req * next = req->next;

                __response_ipc_message(c->port, c->vmid, -EIDRM, c->seq);

                put_ipc_port(c->port);
                __free_msg_qobj(msgq, req);
                req = next;
            }
        }

    msgq->owned = false;
    ret = 0;
    goto out;

err_file:
    DkStreamDelete(file, 0);
    DkObjectClose(file);

out:
    // To wake up any receiver waiting on local message which must
    // now be requested from new owner.
    DkEventSet(msgq->event);
    return ret;
}
Beispiel #10
0
int main (int argc, char ** argv, char ** envp)
{
    char gipc_uri[20];
    int ret;

    DkSetExceptionHandler(handler, PAL_EVENT_MEMFAULT);

    if (argc > 1 && !memcmp(argv[1], "Child", 6)) {
        /* private memory */

        ret = DkStreamRead(pal_control.parent_process, 0, 20, gipc_uri,
                           NULL, 0);

        if (ret > 0) {
            PAL_HANDLE ipc1 = DkStreamOpen(gipc_uri, 0, 0, 0, 0);

            if (ipc1) {
                pal_printf("Join Physical Memory Store OK\n");

                PAL_PTR mem_addr = 0;
                PAL_NUM mem_size = UNIT;
                PAL_FLG mem_prot = PAL_PROT_READ|PAL_PROT_WRITE;

                ret = DkPhysicalMemoryMap(ipc1, 1, &mem_addr, &mem_size,
                                          &mem_prot);

                if (ret > 0) {
                    pal_printf("[Test 1] Physical Memory Map   : %s\n",
                               (char *) mem_addr);
                    memcpy((void *) mem_addr, "Hello World, Bob", 20);
                    pal_printf("[Test 1] Receiver After  Map   : %s\n",
                               (char *) mem_addr);
                }

                ret = 0;
                DkStreamWrite(pal_control.parent_process, 0, sizeof(int),
                              &ret, NULL);
                DkObjectClose(ipc1);
            }
        }

        /* private untouched memory */

        ret = DkStreamRead(pal_control.parent_process, 0, 20, gipc_uri,
                           NULL, 0);

        if (ret > 0) {
            PAL_HANDLE ipc2 = DkStreamOpen(gipc_uri, 0, 0, 0, 0);

            if (ipc2) {
                pal_printf("Join Physical Memory Store OK\n");

                PAL_PTR mem_addr = 0;
                PAL_NUM mem_size = UNIT;
                PAL_FLG mem_prot = PAL_PROT_READ|PAL_PROT_WRITE;

                ret = DkPhysicalMemoryMap(ipc2, 1, &mem_addr, &mem_size,
                                          &mem_prot);

                if (ret > 0) {
                    pal_printf("[Test 2] Physical Memory Map   : %s\n",
                               (char *) mem_addr);
                    memcpy((void *) mem_addr, "Hello World, Bob", 20);
                    pal_printf("[Test 2] Receiver After  Map   : %s\n",
                               (char *) mem_addr);
                }

                ret = 0;
                DkStreamWrite(pal_control.parent_process, 0, sizeof(int),
                              &ret, NULL);
                DkStreamDelete(ipc2, 0);
                DkObjectClose(ipc2);
            }
        }

        /* file-backed memory */

        ret = DkStreamRead(pal_control.parent_process, 0, 20, gipc_uri,
                           NULL, 0);

        if (ret > 0) {
            PAL_HANDLE ipc3 = DkStreamOpen(gipc_uri, 0, 0, 0, 0);

            if (ipc3) {
                pal_printf("Join Physical Memory Store OK\n");

                PAL_PTR mem_addr = 0;
                PAL_NUM mem_size = UNIT;
                PAL_FLG mem_prot = PAL_PROT_READ|PAL_PROT_WRITE;

                ret = DkPhysicalMemoryMap(ipc3, 1, &mem_addr, &mem_size,
                                          &mem_prot);

                if (ret > 0) {
                    pal_printf("[Test 3] Physical Memory Map   : %s\n",
                               (char *) mem_addr);
                    memcpy((void *) mem_addr, "Hello World, Bob", 20);
                    pal_printf("[Test 3] Receiver After  Map   : %s\n",
                               (char *) mem_addr);
                }

                ret = 0;
                DkStreamWrite(pal_control.parent_process, 0, sizeof(int),
                              &ret, NULL);
                DkObjectClose(ipc3);
            }
        }

        /* file-backed memory beyond file size */

        ret = DkStreamRead(pal_control.parent_process, 0, 20, gipc_uri,
                           NULL, 0);

        if (ret > 0) {
            PAL_HANDLE ipc4 = DkStreamOpen(gipc_uri, 0, 0, 0, 0);

            if (ipc4) {
                pal_printf("Join Physical Memory Store OK\n");

                PAL_PTR mem_addr = 0;
                PAL_NUM mem_size = UNIT;
                PAL_FLG mem_prot = PAL_PROT_READ|PAL_PROT_WRITE;

                ret = DkPhysicalMemoryMap(ipc4, 1, &mem_addr, &mem_size,
                                          &mem_prot);

                if (ret > 0) {
                    message = "[Test 4] Physical Memory Map   : Memory Fault\n";
                    *(volatile int *) mem_addr;
                    __asm__ volatile("nop");
                    message = NULL;
                }

                ret = 0;
                DkStreamWrite(pal_control.parent_process, 0, sizeof(int),
                              &ret, NULL);
                DkObjectClose(ipc4);
            }
Beispiel #11
0
long shim_do_sandbox_create (int flags, const char * fs_sb,
                             struct net_sb * net_sb)
{
    unsigned int sbid;
    char uri[24];
    PAL_HANDLE handle = NULL;

    int ret = create_handle("file:sandbox-", uri, 24, &handle, &sbid);
    if (ret < 0)
        return ret;

    debug("create manifest: %s\n", uri);

    struct config_store * newcfg = __alloca(sizeof(struct config_store));
    memset(newcfg, 0, sizeof(struct config_store));
    newcfg->malloc = __malloc;
    newcfg->free = __free;

    if ((ret = copy_config(root_config, newcfg)) < 0) {
        newcfg = NULL;
        goto err;
    }

    if (flags & SANDBOX_FS)
        if ((ret = isolate_fs(newcfg, fs_sb)) < 0)
            goto err;

    if (flags & SANDBOX_NET)
        if ((ret = isolate_net(newcfg, net_sb)) < 0)
            goto err;

    struct cfg_arg arg;
    arg.handle = handle;
    arg.offset = 0;

    if ((ret = write_config(&arg, __write, newcfg)) < 0)
        goto err;

    DkObjectClose(handle);

    PAL_BOL success = DkProcessSandboxCreate(uri, flags & SANDBOX_RPC ?
                                             PAL_SANDBOX_PIPE : 0);

    if (!success) {
        ret = -PAL_ERRNO;
        goto err;
    }

    if (sandbox_info.sbid) {
        if (!sandbox_info.parent_sbid ||
            sandbox_info.parent_vmid != cur_process.vmid) {
            sandbox_info.parent_sbid = sandbox_info.sbid;
            sandbox_info.parent_vmid = cur_process.vmid;
        }
    }

    if (flags & SANDBOX_RPC)
        del_all_ipc_ports(0);

    if ((ret = free_config(root_config)) < 0)
        goto err;

    handle = DkStreamOpen(uri, PAL_ACCESS_RDONLY, 0, 0, 0);

    if (!handle)
        return -PAL_ERRNO;

    root_config = newcfg;
    sandbox_info.sbid = sbid;
    return sbid;

err:
    free_config(newcfg);
    DkStreamDelete(handle, 0);
    DkObjectClose(handle);
    return ret;
}
Beispiel #12
0
int main (int argc, char ** argv)
{
    PAL_HANDLE handles[3];

    if (argc == 2 && !memcmp(argv[1], "Child", 6)) {
        for (int i = 0 ; i < 3 ; i++) {
            handles[i] = DkReceiveHandle(pal_control.parent_process);
            if (handles[i])
                pal_printf("Receive Handle OK\n");
        }

        char buffer[20];

        for (int i = 0 ; i < 3 ; i++) {
            if (!handles[i])
                continue;

            memset(buffer, 0, 20);

            switch(PAL_GET_TYPE(handles[i])) {
                case pal_type_pipesrv: {
                    PAL_HANDLE pipe = DkStreamWaitForClient(handles[i]);

                    if (pipe) {
                        if (DkStreamRead(pipe, 0, 20, buffer, NULL, 0))
                            pal_printf("Receive Pipe Handle: %s\n", buffer);

                        DkObjectClose(pipe);
                    }

                    break;
                }

                case pal_type_udpsrv: {
                    char uri[20];

                    if ((DkStreamRead(handles[i], 0, 20, buffer, &uri, 20)))
                        pal_printf("Receive Socket Handle: %s\n", buffer);

                    break;
                }

                case pal_type_file:
                    if (DkStreamRead(handles[i], 0, 20, buffer, NULL, 0))
                        pal_printf("Receive File Handle: %s\n", buffer);

                    break;

                default:
                    break;
            }

            DkObjectClose(handles[i]);
        }
    } else {
        const char *args[3] = { "SendHandle", "Child", NULL };

        PAL_HANDLE child = DkProcessCreate("file:SendHandle", 0, args);

        if (child) {
            // Sending pipe handle
            handles[0] = DkStreamOpen("pipe.srv:1", PAL_ACCESS_RDWR,
                                      0, PAL_CREAT_TRY, 0);

            if (handles[0]) {
                pal_printf("Send Handle OK\n");

                if (DkSendHandle(child, handles[0])) {
                    DkObjectClose(handles[0]);
                    PAL_HANDLE pipe = DkStreamOpen("pipe:1", PAL_ACCESS_RDWR,
                                                   0, 0, 0);
                    if (pipe) {
                        DkStreamWrite(pipe, 0, 20, "Hello World", NULL);
                        DkObjectClose(pipe);
                    }
                } else {
                    DkObjectClose(handles[0]);
                }
            }

            // Sending udp handle
            handles[1] = DkStreamOpen("udp.srv:127.0.0.1:8000", PAL_ACCESS_RDWR,
                                      0, PAL_CREAT_TRY, 0);

            if (handles[1]) {
                pal_printf("Send Handle OK\n");

                if (DkSendHandle(child, handles[1])) {
                    DkObjectClose(handles[1]);
                    PAL_HANDLE socket = DkStreamOpen("udp:127.0.0.1:8000",
                                                     PAL_ACCESS_RDWR, 0, 0, 0);
                    if (socket) {
                        DkStreamWrite(socket, 0, 20, "Hello World", NULL);
                        DkObjectClose(socket);
                    }
                } else {
                    DkObjectClose(handles[1]);
                }
            }

            handles[2] = DkStreamOpen("file:to_send.tmp", PAL_ACCESS_RDWR,
                                      0600, PAL_CREAT_TRY, 0);

            if (handles[2]) {
                pal_printf("Send Handle OK\n");

                DkStreamWrite(handles[2], 0, 20, "Hello World", NULL);
                DkStreamSetLength(handles[2], 4096);

                DkSendHandle(child, handles[2]);
                DkObjectClose(handles[2]);
            }
        }

        DkObjectClose(child);
    }

    return 0;
}