Пример #1
0
void ringbuffer_produced(ringbuffer_t *buffer, lcb_size_t nb)
{
    lcb_size_t n = ringbuffer_write(buffer, NULL, nb);
    lcb_assert(n == nb);
}
Пример #2
0
/**
 * Extended version of observe command. This allows us to service
 * various forms of higher level operations which use observe in one way
 * or another
 */
lcb_error_t lcb_observe_ex(lcb_t instance,
                           const void *command_cookie,
                           lcb_size_t num,
                           const void *const *items,
                           lcb_observe_type_t type)
{
    lcb_size_t ii;
    lcb_size_t maxix;
    lcb_uint32_t opaque;
    struct lcb_command_data_st ct;
    struct observe_requests_st reqs;

    memset(&reqs, 0, sizeof(reqs));

    if (instance->type != LCB_TYPE_BUCKET) {
        return lcb_synchandler_return(instance, LCB_EBADHANDLE);
    }

    if (instance->vbucket_config == NULL) {
        return lcb_synchandler_return(instance, LCB_CLIENT_ETMPFAIL);
    }

    if (instance->dist_type != VBUCKET_DISTRIBUTION_VBUCKET) {
        return lcb_synchandler_return(instance, LCB_NOT_SUPPORTED);
    }

    opaque = ++instance->seqno;
    ct.cookie = command_cookie;
    maxix = instance->nreplicas;

    if (type == LCB_OBSERVE_TYPE_CHECK) {
        maxix = 0;

    } else {
        if (type == LCB_OBSERVE_TYPE_DURABILITY) {
            ct.flags = LCB_CMD_F_OBS_DURABILITY | LCB_CMD_F_OBS_BCAST;

        } else {
            ct.flags = LCB_CMD_F_OBS_BCAST;
        }
    }

    reqs.nrequests = instance->nservers;
    reqs.requests = calloc(reqs.nrequests, sizeof(*reqs.requests));

    for (ii = 0; ii < num; ii++) {
        const void *key, *hashkey;
        lcb_size_t nkey, nhashkey;
        int vbid, jj;

        if (type == LCB_OBSERVE_TYPE_DURABILITY) {
            const lcb_durability_entry_t *ent = items[ii];
            key = ent->request.v.v0.key;
            nkey = ent->request.v.v0.nkey;
            hashkey = ent->request.v.v0.hashkey;
            nhashkey = ent->request.v.v0.nhashkey;
        } else {
            const lcb_observe_cmd_t *ocmd = items[ii];
            key = ocmd->v.v0.key;
            nkey = ocmd->v.v0.nkey;
            hashkey = ocmd->v.v0.hashkey;
            nhashkey = ocmd->v.v0.nhashkey;
        }
        if (!nhashkey) {
            hashkey = key;
            nhashkey = nkey;
        }

        vbid = vbucket_get_vbucket_by_key(instance->vbucket_config,
                                          hashkey,
                                          nhashkey);

        for (jj = -1; jj < (int)maxix; jj++) {
            struct observe_st *rr;

            int idx = vbucket_get_replica(instance->vbucket_config,
                                          vbid,
                                          jj);

            if (idx < 0 || idx > (int)instance->nservers) {
                if (jj == -1) {
                    destroy_requests(&reqs);
                    return lcb_synchandler_return(instance, LCB_NO_MATCHING_SERVER);
                }
                continue;
            }
            lcb_assert(idx < (int)reqs.nrequests);
            rr = reqs.requests + idx;

            if (!rr->allocated) {
                if (!init_request(rr)) {
                    destroy_requests(&reqs);
                    return lcb_synchandler_return(instance, LCB_CLIENT_ENOMEM);
                }
            }

            {
                lcb_uint16_t vb = htons((lcb_uint16_t)vbid);
                lcb_uint16_t len = htons((lcb_uint16_t)nkey);

                rr->packet.message.header.request.magic = PROTOCOL_BINARY_REQ;
                rr->packet.message.header.request.opcode = CMD_OBSERVE;
                rr->packet.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
                rr->packet.message.header.request.opaque = opaque;

                ringbuffer_ensure_capacity(&rr->body,
                                           sizeof(vb) + sizeof(len) + nkey);
                rr->nbody += ringbuffer_write(&rr->body, &vb, sizeof(vb));
                rr->nbody += ringbuffer_write(&rr->body, &len, sizeof(len));
                rr->nbody += ringbuffer_write(&rr->body, key, nkey);
            }
        }
    }

    for (ii = 0; ii < reqs.nrequests; ii++) {
        struct observe_st *rr = reqs.requests + ii;
        struct lcb_server_st *server = instance->servers + ii;
        char *tmp;

        if (!rr->allocated) {
            continue;
        }

        rr->packet.message.header.request.bodylen = ntohl((lcb_uint32_t)rr->nbody);
        ct.start = gethrtime();

        lcb_server_start_packet_ct(server, &ct, rr->packet.bytes,
                                   sizeof(rr->packet.bytes));

        if (ringbuffer_is_continous(&rr->body, RINGBUFFER_READ, rr->nbody)) {
            tmp = ringbuffer_get_read_head(&rr->body);
            TRACE_OBSERVE_BEGIN(&rr->packet, server->authority, tmp, rr->nbody);
            lcb_server_write_packet(server, tmp, rr->nbody);
        } else {
            tmp = malloc(ringbuffer_get_nbytes(&rr->body));
            if (!tmp) {
                /* FIXME by this time some of requests might be scheduled */
                destroy_requests(&reqs);
                return lcb_synchandler_return(instance, LCB_CLIENT_ENOMEM);
            } else {
                ringbuffer_read(&rr->body, tmp, rr->nbody);
                TRACE_OBSERVE_BEGIN(&rr->packet, server->authority, tmp, rr->nbody);
                lcb_server_write_packet(server, tmp, rr->nbody);
            }
        }
        lcb_server_end_packet(server);
        lcb_server_send_packets(server);
    }

    destroy_requests(&reqs);
    return lcb_synchandler_return(instance, LCB_SUCCESS);
}
Пример #3
0
LIBCOUCHBASE_API
lcb_error_t lcb_observe(lcb_t instance,
                        const void *command_cookie,
                        lcb_size_t num,
                        const lcb_observe_cmd_t *const *items)
{
    int vbid, idx, jj;
    lcb_size_t ii;
    lcb_uint32_t opaque;
    struct observe_st *requests;

    /* we need a vbucket config before we can start getting data.. */
    if (instance->vbucket_config == NULL) {
        switch (instance->type) {
        case LCB_TYPE_CLUSTER:
            return lcb_synchandler_return(instance, LCB_EBADHANDLE);
        case LCB_TYPE_BUCKET:
        default:
            return lcb_synchandler_return(instance, LCB_CLIENT_ETMPFAIL);
        }
    }

    if (instance->dist_type != VBUCKET_DISTRIBUTION_VBUCKET) {
        return lcb_synchandler_return(instance, LCB_NOT_SUPPORTED);
    }

    /* the list of pointers to body buffers for each server */
    requests = calloc(instance->nservers, sizeof(struct observe_st));
    opaque = ++instance->seqno;
    for (ii = 0; ii < num; ++ii) {
        const void *key = items[ii]->v.v0.key;
        lcb_size_t nkey = items[ii]->v.v0.nkey;
        const void *hashkey = items[ii]->v.v0.hashkey;
        lcb_size_t nhashkey = items[ii]->v.v0.nhashkey;

        if (nhashkey == 0) {
            hashkey = key;
            nhashkey = nkey;
        }

        vbid = vbucket_get_vbucket_by_key(instance->vbucket_config, hashkey,
                                          nhashkey);
        for (jj = -1; jj < instance->nreplicas; ++jj) {
            struct observe_st *rr;
            /* it will increment jj to get server index, so (-1 + 1) = 0 (master) */
            idx = vbucket_get_replica(instance->vbucket_config, vbid, jj);
            if ((idx < 0 || idx > (int)instance->nservers)) {
                /* the config says that there is no server yet at that position (-1) */
                if (jj == -1) {
                    /* master node must be available */
                    destroy_requests(requests, instance->nservers);
                    return lcb_synchandler_return(instance, LCB_NETWORK_ERROR);
                } else {
                    continue;
                }
            }
            rr = requests + idx;
            if (!rr->allocated) {
                if (!init_request(rr)) {
                    destroy_requests(requests, instance->nservers);
                    return lcb_synchandler_return(instance, LCB_CLIENT_ENOMEM);
                }
                rr->req.message.header.request.magic = PROTOCOL_BINARY_REQ;
                rr->req.message.header.request.opcode = CMD_OBSERVE;
                rr->req.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
                rr->req.message.header.request.opaque = opaque;
            }

            {
                lcb_uint16_t vb = htons((lcb_uint16_t)vbid);
                lcb_uint16_t len = htons((lcb_uint16_t)nkey);
                ringbuffer_ensure_capacity(&rr->body, sizeof(vb) + sizeof(len) + nkey);
                rr->nbody += ringbuffer_write(&rr->body, &vb, sizeof(vb));
                rr->nbody += ringbuffer_write(&rr->body, &len, sizeof(len));
                rr->nbody += ringbuffer_write(&rr->body, key, nkey);
            }
        }
    }

    for (ii = 0; ii < instance->nservers; ++ii) {
        struct observe_st *rr = requests + ii;
        lcb_server_t *server = instance->servers + ii;

        if (rr->allocated) {
            char *tmp;
            rr->req.message.header.request.bodylen = ntohl((lcb_uint32_t)rr->nbody);
            lcb_server_start_packet(server, command_cookie, rr->req.bytes, sizeof(rr->req.bytes));
            if (ringbuffer_is_continous(&rr->body, RINGBUFFER_READ, rr->nbody)) {
                tmp = ringbuffer_get_read_head(&rr->body);
                TRACE_OBSERVE_BEGIN(&rr->req, server->authority, tmp, rr->nbody);
                lcb_server_write_packet(server, tmp, rr->nbody);
            } else {
                tmp = malloc(ringbuffer_get_nbytes(&rr->body));
                if (!tmp) {
                    /* FIXME by this time some of requests might be scheduled */
                    destroy_requests(requests, instance->nservers);
                    return lcb_synchandler_return(instance, LCB_CLIENT_ENOMEM);
                } else {
                    ringbuffer_read(&rr->body, tmp, rr->nbody);
                    TRACE_OBSERVE_BEGIN(&rr->req, server->authority, tmp, rr->nbody);
                    lcb_server_write_packet(server, tmp, rr->nbody);
                }
            }
            lcb_server_end_packet(server);
            lcb_server_send_packets(server);
        }
    }

    destroy_requests(requests, instance->nservers);
    return lcb_synchandler_return(instance, LCB_SUCCESS);
}
Пример #4
0
static int socks5_src_do_connect(struct sserver_handle *handle, struct ssession *session) {
    
    // 1. parse
    // 2. clear buf;
    // 3. connect to dest addr
    // 4. set session.dstfd
    // 5. add response to sendbuf;
    // 6. add fd to writefds
    // 7. set session state to SSESSION_STATE_TRANSMIT
    
    /*
     rep:
     0x00        成功
     0x01        一般性失败
     0x02        规则不允许转发
     0x03        网络不可达
     0x04        主机不可达
     0x05        连接拒绝
     0x06        TTL超时
     0x07        不支持请求包中的CMD
     0x08        不支持请求包中的ATYP
     0x09-0xFF   unassigned
     */
    
    int ret = 0;
    char ver = 0x00;
    char cmd = 0x00;
    char rsv = 0x00;
    char atyp = 0x00;
    char ndstaddr = 0x00;
    uint32_t ip = 0x00;
    char dstaddr[256] = {0x00};
    uint16_t dstport = 0;
    
    char rep = 0x00;
    char nbndaddr = 0x00;
    char bndaddr[256] = {0x00};
    uint16_t bndport = 0;
    int nread = 0;
    
    struct ringbuffer_tran tran;
    struct ringbuffer *tranrb = NULL;
    
    tranrb = ringbuffer_transaction_begin(session->dstbuf, &tran);
    
    nread = ringbuffer_transaction_read(tranrb, &ver, 1);
    if(nread <= 0) {
        ringbuffer_transaction_rollback(session->dstbuf, &tran);
        return SE_NEEDMORE;
    }
    
    nread = ringbuffer_transaction_read(tranrb, &cmd, 1);
    if(nread <= 0) {
        ringbuffer_transaction_rollback(session->dstbuf, &tran);
        return SE_NEEDMORE;
    }
    
    nread = ringbuffer_transaction_read(tranrb, &rsv, 1);
    if(nread <= 0) {
        ringbuffer_transaction_rollback(session->dstbuf, &tran);
        return SE_NEEDMORE;
    }
    
    nread = ringbuffer_transaction_read(tranrb, &atyp, 1);
    if(nread <= 0) {
        ringbuffer_transaction_rollback(session->dstbuf, &tran);
        return SE_NEEDMORE;
    }
    
    switch (cmd) {
        case 0x01:
            break;
        case 0x02:
        case 0x03:
        default:
            rep = 0x07;
            goto pre_send;
            break;
    }
    
    switch(atyp) {
        case 0x01:	// ipv4
            nread = ringbuffer_transaction_read(tranrb, &ip, 4);
            if(nread <= 0) {
                ringbuffer_transaction_rollback(session->dstbuf, &tran);
                return SE_NEEDMORE;
            }
            nread = ringbuffer_transaction_read(tranrb, &dstport, 2);
            if(nread <= 0) {
                ringbuffer_transaction_rollback(session->dstbuf, &tran);
                return SE_NEEDMORE;
            }
            session->dstfd = tcp_socket_connect_with_ip(ip, dstport);
            break;
        case 0x03:	// domain
            nread = ringbuffer_transaction_read(tranrb, &ndstaddr, 1);
            if(nread <= 0) {
                ringbuffer_transaction_rollback(session->dstbuf, &tran);
                return SE_NEEDMORE;
            }
            
            nread = ringbuffer_transaction_read(tranrb, dstaddr, ndstaddr);
            if(nread <= 0) {
                ringbuffer_transaction_rollback(session->dstbuf, &tran);
                return SE_NEEDMORE;
            }
            
            nread = ringbuffer_transaction_read(tranrb, &dstport, 2);
            if(nread <= 0) {
                ringbuffer_transaction_rollback(session->dstbuf, &tran);
                return SE_NEEDMORE;
            }
            session->dstfd = tcp_socket_connect_with_domain(dstaddr, dstport);
            break;
        case 0x04:	// ipv6
            rep = 0x08;
            goto pre_send;
            break;
    }
    
    if(session->dstfd < 0) {
        switch (errno) {
            case ENETUNREACH:
                rep = 0x03;
                break;
            case EHOSTUNREACH:
                rep = 0x04;
                break;
            case ECONNREFUSED:
                rep = 0x05;
                break;
            default:
                rep = 0x01;
                break;
        }
    } else {
        FD_SET(session->dstfd, &handle->server->readfds);
        if(handle->server->maxfd < session->dstfd)
            handle->server->maxfd = session->dstfd;
    }

pre_send:
    atyp = 0x01;
    nbndaddr = 4;
    bndaddr[0] = '\0';
    bndaddr[1] = '\0';
    bndaddr[2] = '\0';
    bndaddr[3] = '\0';
    
    ringbuffer_clear(session->dstbuf);
    ringbuffer_write(session->srcbuf, &ver, 1);
    ringbuffer_write(session->srcbuf, &rep, 1);
    ringbuffer_write(session->srcbuf, &rsv, 1);
    ringbuffer_write(session->srcbuf, &atyp, 1);
    ringbuffer_write(session->srcbuf, &nbndaddr, 1);
    ringbuffer_write(session->srcbuf, bndaddr, nbndaddr);
    ringbuffer_write(session->srcbuf, &bndport, 2);
    
    FD_SET(session->srcfd, &handle->server->writefds);
    if(handle->server->maxfd < session->srcfd)
        handle->server->maxfd = session->srcfd;
    
    session->state = SSESSION_STATE_TRANSMIT;
    return ret;
}
Пример #5
0
int main(int argc, char **argv) {
	char buf[1024];

	fd_set *     readselect  = malloc(sizeof(fd_set));
	fd_set *     writeselect = malloc(sizeof(fd_set));
	fd_set *     errorselect = malloc(sizeof(fd_set));
	unsigned int maxfd = 3;

	readsockets  = array_init(); readsockets->name = "read";
	writesockets = array_init(); writesockets->name = "write";
	errorsockets = array_init(); errorsockets->name = "error";

	buffer_socket * stdin_sock = malloc(sizeof(buffer_socket));
	stdin_sock->type = SOCKTYPE_LOCAL;
	stdin_sock->fd   = STDIN_FILENO;
	ringbuffer_init(&stdin_sock->rxbuffer);
	ringbuffer_init(&stdin_sock->txbuffer);

	readsockets = array_push(readsockets, stdin_sock);
	errorsockets = array_push(errorsockets, stdin_sock);

	char * printer_port = DEFAULT_PORT;
	int printer_baud = DEFAULT_BAUD;

	// TODO: parse command line options

	printer_socket *printer = new_printer_socket(printer_port, printer_baud);

	file_socket *file = NULL;

	/***********************************************************************\
	*                                                                       *
	* Now set up network sockets                                            *
	*                                                                       *
	\***********************************************************************/

	new_listen_socket(DEFAULT_LISTEN_PORT, SOCKTYPE_CLIENT);
	new_listen_socket(DEFAULT_LISTEN_PORT + 1, SOCKTYPE_HTTP);

	/***********************************************************************\
	*                                                                       *
	* Main Loop                                                             *
	*                                                                       *
	\***********************************************************************/

	int running = 1;

	while (running) {
		FD_ZERO(readselect);
		FD_ZERO(writeselect);
		FD_ZERO(errorselect);
		for (int i = 0; i < readsockets->length; i++) {
			local_socket *ls = ((local_socket *) readsockets->data[i]);
			int fd = ls->fd;
			//printf("check read %d\n", ((local_socket *) readsockets->data[i])->fd);
			if ((ls->type == SOCKTYPE_PRINTER) || (printer->tokens > 0)) {
				FD_SET(fd, readselect);
				if (fd >= maxfd)
					maxfd = fd + 1;
			}
		}
		for (int i = 0; i < writesockets->length; i++) {
			local_socket *ls = ((local_socket *) writesockets->data[i]);
			int fd = ls->fd;
			//printf("check write %d\n", ((local_socket *) writesockets->data[i])->fd);
			if ((ls->type != SOCKTYPE_PRINTER) || (printer->tokens > 0)) {
				FD_SET(fd, writeselect);
				if (fd >= maxfd)
					maxfd = fd + 1;
			}
		}
		for (int i = 0; i < errorsockets->length; i++) {
			local_socket *ls = ((local_socket *) errorsockets->data[i]);
			int fd = ls->fd;
			//printf("check error %d\n", ((local_socket *) errorsockets->data[i])->fd);
			FD_SET(((local_socket *) errorsockets->data[i])->fd, errorselect);
			if (fd >= maxfd)
				maxfd = fd + 1;
		}
		select(maxfd, readselect, writeselect, errorselect, NULL);

		/*******************************************************************\
		*                                                                   *
		* Check Errors                                                      *
		*                                                                   *
		\*******************************************************************/
		for (int i = 0; i < errorsockets->length; i++) {
			local_socket *s = (local_socket *) errorsockets->data[i];
			if (FD_ISSET(s->fd, errorselect)) {
				printf("error on %d: %p\n", s->fd, s);
				switch (s->type) {
					case SOCKTYPE_LOCAL:
						break;
					case SOCKTYPE_PRINTER:
						break;
					case SOCKTYPE_CLIENT:
						break;
					case SOCKTYPE_LISTEN:
						break;
				} /* switch s->type */
			} /* if FD_ISSET fd, errorselect */
		} /* for errorsockets */

		/*******************************************************************\
		*                                                                   *
		* Check Readable Sockets                                            *
		*                                                                   *
		\*******************************************************************/
		for (int i = 0; i < readsockets->length; i++) {
			local_socket *s = (local_socket *) readsockets->data[i];
			if (FD_ISSET(s->fd, readselect)) {
				//printf("read %d (type %d)\n", s->fd, s->type);
				switch (s->type) {
					case SOCKTYPE_LOCAL: {
						buffer_socket *sock = (buffer_socket *) s;
						unsigned int r = ringbuffer_writefromfd(&sock->rxbuffer, s->fd, ringbuffer_canwrite(&sock->rxbuffer));
						if (r == 0) {
							printf("EOF on stdin, exiting...\n");
							exit(0);
						}
						break;
					}
					case SOCKTYPE_CLIENT: {
						client_socket *sock = (client_socket *) s;
						unsigned int r = ringbuffer_writefromfd(&sock->inbuffer, s->fd, ringbuffer_canwrite(&sock->inbuffer));
						//printf("writefromfd %p %d %d got %d nl %d\n", &sock->rxbuffer, s->fd, ringbuffer_canwrite(&sock->rxbuffer), r, sock->rxbuffer.nl);
						if (r == 0) {
							sock2a(&sock->addr, buf, BUFFER_SIZE);
							printf("client %s disconnected\n", buf);
							close(sock->fd);
							readsockets = array_delete(readsockets, sock);
							writesockets = array_delete(writesockets, sock);
							errorsockets = array_delete(errorsockets, sock);
							free(sock);
							sock = NULL;
						}
						else if (sock->inbuffer.nl > 0) {
							char linebuffer[256];
							while (ringbuffer_peekline(&sock->inbuffer, linebuffer, sizeof(linebuffer))) {
								switch (detect_line_type(linebuffer)) {
									case LINETYPE_GCODE: {
										unsigned int i = ringbuffer_readline(&sock->rxbuffer, linebuffer, sizeof(linebuffer));
										ringbuffer_write(&sock->rxbuffer, linebuffer, i);
										break;
									};
									case LINETYPE_SIMPLECMD: {
										unsigned int i = ringbuffer_readline(&sock->rxbuffer, linebuffer, sizeof(linebuffer));
										parse_line(linebuffer);
										break;
									};
								}
							}
						}
						break;
					}
					case SOCKTYPE_PRINTER: {
						//printf("can read printer\n");
						printer_socket *sock = (printer_socket *) s;
						unsigned int r = ringbuffer_writefromfd(&sock->rxbuffer, s->fd, BUFFER_SIZE);
						if (r == 0) {
							//printf(" %d bytes: printer disconnected, trying to reconnect...\n", r);
							close(s->fd);
							readsockets = array_delete(readsockets, sock);
							writesockets = array_delete(writesockets, sock);
							errorsockets = array_delete(errorsockets, sock);
							free(sock);
							sock = NULL;
							sock = new_printer_socket(printer_port, printer_baud);
							readsockets = array_push(readsockets, sock);
							errorsockets = array_push(errorsockets, sock);
						}
						else {
							//printf(" %d bytes, %d newlines", r, sock->rxbuffer.nl);
							while (sock->rxbuffer.nl > 0) {
								char line[BUFFER_SIZE];
								int r = ringbuffer_readline(&sock->rxbuffer, line, BUFFER_SIZE);
								if (sock->lastmsgsock->fd > 2)
									printf("< %s", line);
								int m = snprintf(buf, BUFFER_SIZE, "< %s", line);
								if (sock->lastmsgsock->type == SOCKTYPE_LOCAL) {
									int i = 0;
									do {
										i += write(sock->lastmsgsock->fd, &buf[i], m - i);
									} while (i < m);
								}
								else if (sock->lastmsgsock->type == SOCKTYPE_CLIENT) {
									//printf("client type\n");
									client_socket *cs = (client_socket *) sock->lastmsgsock;
									ringbuffer_write(&cs->txbuffer, line, r);
									if (array_indexof(writesockets, cs) == -1) {
										writesockets = array_push(writesockets, cs);
										//printf("pushed %p/%d to writesockets\n", cs, cs->socket.fd);
									}
								}
								if (strncmp(line, "ok", 2) == 0) {
									//fprintf(stderr, "got token!");
									if (sock->tokens < sock->maxtoken)
										sock->tokens++;
									for (int i = 0; i < errorsockets->length; i++) {
										if (((local_socket *) errorsockets->data[i])->type == SOCKTYPE_CLIENT)
											readsockets = array_push(readsockets, errorsockets->data[i]);
									}
									if (file != NULL)
										writesockets = array_push(writesockets, sock);
									//fprintf(stderr, " tokens: %d\n", sock->tokens);
								}
								else {
									//fprintf(stderr, "no token\n");
								}
							}
						}
						break;
					}
					case SOCKTYPE_LISTEN: {
						listen_socket *ls = (listen_socket *) s;
						if (ls->protocol == SOCKTYPE_HTTP) {
							new_http_socket(ls);
						}
						else if (ls->protocol == SOCKTYPE_CLIENT) {
							new_client_socket(ls);
						}
						break;
					}
					case SOCKTYPE_FILE: {
						break;
					}
					case SOCKTYPE_HTTP: {
						http_socket *sock = (http_socket *) s;
						unsigned int r = ringbuffer_writefromfd(&sock->rxbuffer, s->fd, ringbuffer_canwrite(&sock->rxbuffer));
						if (r == 0) {
							sock2a(&sock->addr, buf, BUFFER_SIZE);
							printf("client %s disconnected\n", buf);
							close(sock->fd);
							readsockets = array_delete(readsockets, sock);
							writesockets = array_delete(writesockets, sock);
							errorsockets = array_delete(errorsockets, sock);
							free(sock);
							sock = NULL;
						}
						else {
						}
						break;
					}
				} /* switch s->type */
			} /* if FD_ISSET fd, readselect */
		} /* for readsockets */

		/*******************************************************************\
		*                                                                   *
		* Check Writable Sockets                                            *
		*                                                                   *
		\*******************************************************************/
		for (int i = 0; i < writesockets->length; i++) {
			local_socket *s = (local_socket *) writesockets->data[i];
			if (FD_ISSET(s->fd, writeselect)) {
				//printf("write %d", s->fd);
				switch (s->type) {
					case SOCKTYPE_LOCAL:
					case SOCKTYPE_CLIENT:
					case SOCKTYPE_HTTP: {
						//printf("write client socket\n");
						buffer_socket *sock = (buffer_socket *) s;
						if (ringbuffer_canread(&sock->txbuffer) > 0) {
							//printf("readtofd %d %p: %d\n", s->fd, &sock->txbuffer,
								ringbuffer_readtofd(&sock->txbuffer, s->fd);
							//);
						}
						if (ringbuffer_canread(&sock->txbuffer) == 0) {
							//printf("client txbuffer empty\n");
							writesockets = array_delete(writesockets, s);
						}
						break;
					}
					case SOCKTYPE_PRINTER: {
						printer_socket *sock = (printer_socket *) s;
						//printf("write: nl: %d\n", sock->txbuffer.nl);
						if (sock->rxbuffer.nl == 0) {
							int i = (sock->lastmsgindex + 1) % errorsockets->length;
							for (int j = 0; j <= errorsockets->length; j++) {
								buffer_socket * x = errorsockets->data[i];
								if (x->type == SOCKTYPE_LOCAL || x->type == SOCKTYPE_CLIENT || x->type == SOCKTYPE_FILE) {
									int r = ringbuffer_readline(&x->rxbuffer, buf, BUFFER_SIZE);
									ringbuffer_write(&printer->txbuffer, buf, r);
									sock->lastmsgsock = (local_socket *) x;
									sock->lastmsgindex = i;
									break;
								}
								i = (i + 1) % errorsockets->length;
							}
						}
						if (sock->txbuffer.nl > 0) {
							//printf("write: nl: %d\n", sock->txbuffer.nl);
							unsigned int r = ringbuffer_readline(&sock->txbuffer, buf, BUFFER_SIZE);
							buf[r] = 0;
							printf(">>> %s", buf);
							int i = 0;
							do {
								i += write(s->fd, &buf[i], r - i);
							} while (i < r);
							sock->tokens--;
							if (sock->tokens == 0) {
								for (int i = 0; i < errorsockets->length; i++) {
									if (((local_socket *) errorsockets->data[i])->type == SOCKTYPE_CLIENT)
										readsockets = array_delete(readsockets, errorsockets->data[i]);
								}
							}
						}
						else if ((sock->tokens > 0) && (file != NULL) && (file->paused == 0)) {
							if ((ringbuffer_canwrite(&file->rxbuffer) > 0) && (file->eof == 0)) {
								int w = ringbuffer_writefromfd(&file->rxbuffer, file->fd, BUFFER_SIZE);
								if (w == 0)
									file->eof = 1;
							}
							if (file->rxbuffer.nl > 0) {
								int r = ringbuffer_readline(&file->rxbuffer, buf, BUFFER_SIZE);
								buf[r] = 0;
								printf(">>> %s", buf);
								int i = 0;
								do {
									i += write(s->fd, &buf[i], r - i);
								} while (i < r);
								sock->tokens--;
							}
							else if (file->eof) {
								// file is completely printed
								printf("File %s complete. Print time: \n", file->filename);
								// TODO:close file
							}
						}
						if ((ringbuffer_canread(&sock->txbuffer) == 0) || (sock->tokens == 0))
							writesockets = array_delete(writesockets, sock);
						break;
					}
				} /* switch s->type */
			} /* if FD_ISSET fd, writeselect */
		} /* for writesockets */
	} /* while running */

	return 0;
} /* main() */
Пример #6
0
static libcouchbase_error_t create_memcached(const struct libcouchbase_memcached_st *user,
                                             VBUCKET_CONFIG_HANDLE vbconfig)
{
    ringbuffer_t buffer;
    char *copy = strdup(user->serverlist);
    char head[1024];
    int first;
    char *ptr = copy;
    int fail;
    libcouchbase_ssize_t offset = 0;

    if (copy == NULL) {
        return LIBCOUCHBASE_CLIENT_ENOMEM;
    }

    if (ringbuffer_initialize(&buffer, 1024) == -1) {
        free(copy);
        return LIBCOUCHBASE_CLIENT_ENOMEM;
    }

    head[0] = '\0';
    offset += snprintf(head + offset, sizeof(head) - offset, "%s", "{");
    offset += snprintf(head + offset, sizeof(head) - offset, "%s",
                       "\"bucketType\":\"memcached\",");
    offset += snprintf(head + offset, sizeof(head) - offset, "%s",
                       "\"nodeLocator\":\"ketama\",");
    if (user->username != NULL) {
        offset += snprintf(head + offset, sizeof(head) - offset, "%s",
                           "\"authType\":\"sasl\",");
        offset += snprintf(head + offset, sizeof(head) - offset, "%s",
                           "\"name\":\"");
        offset += snprintf(head + offset, sizeof(head) - offset, "%s",
                           user->username);
        offset += snprintf(head + offset, sizeof(head) - offset, "%s", "\",");
        if (user->password != NULL) {
            offset += snprintf(head + offset, sizeof(head) - offset, "%s",
                               "\"saslPassword\":\"");
            offset += snprintf(head + offset, sizeof(head) - offset, "%s",
                               user->password);
            offset += snprintf(head + offset, sizeof(head) - offset, "%s",
                               "\",");
        }
    }

    offset += snprintf(head + offset, sizeof(head) - offset, "%s",
                       "\"nodes\": [");
    ringbuffer_write(&buffer, head, strlen(head));

    /* Let's add the hosts... */
    first = 1;
    do {
        char *tok;
        char *next = strchr(ptr, ';');
        const char *port = "11211";
        libcouchbase_ssize_t length;

        if (next != NULL) {
            *next = '\0';
        }

        tok = strchr(ptr, ':');
        if (tok != NULL) {
            *tok = '\0';
            port = tok + 1;
            if ((tok = strchr(ptr, ':')) != NULL) {
                *tok = '\0'; /* Remove weight for now */
            }
        }

        length = snprintf(head, sizeof(head),
                          "%c{\"hostname\":\"%s\",\"ports\":{\"direct\":%s}}",
                          first ? ' ' : ',', ptr, port);
        first = 0;

        if (ringbuffer_ensure_capacity(&buffer, length) == -1) {
            free(copy);
            return LIBCOUCHBASE_CLIENT_ENOMEM;
        }

        ringbuffer_write(&buffer, head, length);

        if (next != NULL) {
            ptr = next + 1;
        } else {
            ptr = NULL;
        }
    } while (ptr != NULL);

    if (ringbuffer_ensure_capacity(&buffer, 3) == -1) {
        free(copy);
        return LIBCOUCHBASE_CLIENT_ENOMEM;
    }

    ringbuffer_write(&buffer, "]}", 3); /* Include '\0' */

    /* Now let's parse the config! */
    fail = vbucket_config_parse(vbconfig, LIBVBUCKET_SOURCE_MEMORY,
                                (char *)ringbuffer_get_read_head(&buffer));
    free(copy);
    ringbuffer_destruct(&buffer);

    if (fail) {
        /* Hmm... internal error! */
        return LIBCOUCHBASE_EINTERNAL;
    }

    return LIBCOUCHBASE_SUCCESS;
}
Пример #7
0
static lcb_error_t
obs_ctxadd(lcb_MULTICMD_CTX *mctx, const lcb_CMDOBSERVE *cmd)
{
    const void *hk;
    lcb_SIZE nhk;
    int vbid;
    unsigned maxix;
    int ii;
    OBSERVECTX *ctx = CTX_FROM_MULTI(mctx);
    lcb_t instance = ctx->instance;
    mc_CMDQUEUE *cq = &instance->cmdq;

    if (LCB_KEYBUF_IS_EMPTY(&cmd->key)) {
        return LCB_EMPTY_KEY;
    }

    if (cq->config == NULL) {
        return LCB_CLIENT_ETMPFAIL;
    }

    if (instance->dist_type != LCBVB_DIST_VBUCKET) {
        return LCB_NOT_SUPPORTED;
    }

    mcreq_extract_hashkey(&cmd->key, &cmd->hashkey, 24, &hk, &nhk);
    vbid = lcbvb_k2vb(cq->config, hk, nhk);
    maxix = LCBVB_NREPLICAS(cq->config);

    for (ii = -1; ii < (int)maxix; ++ii) {
        struct observe_st *rr;
        lcb_U16 vb16, klen16;
        int ix;

        if (ii == -1) {
            ix = lcbvb_vbmaster(cq->config, vbid);
            if (ix < 0) {
                return LCB_NO_MATCHING_SERVER;
            }
        } else {
            ix = lcbvb_vbreplica(cq->config, vbid, ii);
            if (ix < 0) {
                continue;
            }
        }

        lcb_assert(ix < (int)ctx->nrequests);
        rr = ctx->requests + ix;
        if (!rr->allocated) {
            if (!init_request(rr)) {
                return LCB_CLIENT_ENOMEM;
            }
        }

        vb16 = htons((lcb_U16)vbid);
        klen16 = htons((lcb_U16)cmd->key.contig.nbytes);
        ringbuffer_ensure_capacity(&rr->body, sizeof(vb16) + sizeof(klen16));
        ringbuffer_write(&rr->body, &vb16, sizeof vb16);
        ringbuffer_write(&rr->body, &klen16, sizeof klen16);
        ringbuffer_write(&rr->body, cmd->key.contig.bytes, cmd->key.contig.nbytes);
        ctx->remaining++;
        if (cmd->cmdflags & LCB_CMDOBSERVE_F_MASTER_ONLY) {
            break;
        }
    }
    return LCB_SUCCESS;
}
Пример #8
0
void * DMXThread(void * v_arg)
{
	pthread_t file_thread;
	struct filenames_t filename_data;
	char filename_extension[3];
	ringbuffer_data_t vec[2];
	ssize_t written;
	ssize_t todo = 0;
	ssize_t todo2;
	unsigned char buf[TS_SIZE];
	int     offset = 0;
	ssize_t r = 0;
	struct pollfd pfd = {*(int*)v_arg, POLLIN|POLLERR,0 };
	int pres;

	ringbuffer_t * ringbuf = ringbuffer_create(ringbuffersize);

	if (!ringbuf)
	{
		exit_flag = STREAM2FILE_STATUS_RECORDING_THREADS_FAILED;
		puts("[stream2file]: error allocating ringbuffer! (out of memory?)"); 
	}
	else
		fprintf(stderr, "[stream2file] allocated ringbuffer size: %ld\n", ringbuffer_write_space(ringbuf));

	filename_data.ringbuffer = ringbuf;

	if (v_arg == &dvrfd)
	{
		filename_data.extension = "ts";
	}
	else
	{
		for (int i = 0; i < MAXPIDS; i++)
			if (v_arg == (&(demuxfd[i])))
				sprintf(filename_extension, "%u", i);
		filename_data.extension = filename_extension;
	}

	if (pthread_create(&file_thread, 0, FileThread, &filename_data) != 0)
	{
		exit_flag = STREAM2FILE_STATUS_RECORDING_THREADS_FAILED;
		puts("[stream2file]: error creating file_thread! (out of memory?)"); 
	}

	if (v_arg == &dvrfd)
		while (exit_flag == STREAM2FILE_STATUS_RUNNING)
		{
			if ((pres=poll (&pfd, 1, 15000))>0)
			{
				if (!(pfd.revents&POLLIN))
				{
					printf ("[stream2file]: PANIC: error reading from demux, bailing out\n");
					exit_flag = STREAM2FILE_STATUS_READ_FAILURE;
				}
				r = read(*(int *)v_arg, &(buf[0]), TS_SIZE);
#ifdef HAVE_TRIPLEDRAGON
				if (r < 0)
				{
					perror("stream2file read DMX");
					exit_flag = STREAM2FILE_STATUS_READ_FAILURE;
					break;
				}
#endif
				if (r > 0)
				{
					offset = sync_byte_offset(&(buf[0]), r);
					if (offset != -1)
						break;
				}
			}
			else if (!pres)
			{
				printf ("[stream2file]: timeout from demux\n");
			}
		}
	else
		offset = 0;

	if (exit_flag == STREAM2FILE_STATUS_RUNNING)
	{
		written = ringbuffer_write(ringbuf, (char *)&(buf[offset]), r - offset);
		// TODO: Retry
		if (written != r - offset) {
			printf("PANIC: wrote less than requested to ringbuffer, written %d, requested %d\n", written, r - offset);
			exit_flag = STREAM2FILE_STATUS_BUFFER_OVERFLOW;
		}
		todo = IN_SIZE - (r - offset);
	}

	/* IN_SIZE > TS_SIZE => todo > 0 */

	while (exit_flag == STREAM2FILE_STATUS_RUNNING)
	{
		ringbuffer_get_write_vector(ringbuf, &(vec[0]));
		todo2 = todo - vec[0].len;
		if (todo2 < 0)
		{
			todo2 = 0;
		}
		else
		{
			if (((size_t)todo2) > vec[1].len)
			{
				printf("PANIC: not enough space in ringbuffer, available %d, needed %d\n", vec[0].len + vec[1].len, todo + todo2);
				exit_flag = STREAM2FILE_STATUS_BUFFER_OVERFLOW;
			}
			todo = vec[0].len;
		}

		while (exit_flag == STREAM2FILE_STATUS_RUNNING)
		{
			if ((pres=poll (&pfd, 1, 5000))>0)
			{
				if (!(pfd.revents&POLLIN))
				{
					printf ("PANIC: error reading from demux, bailing out\n");
					exit_flag = STREAM2FILE_STATUS_READ_FAILURE;
				}
				r = read(*(int *)v_arg, vec[0].buf, todo);
				if (r > 0)
				{
					ringbuffer_write_advance(ringbuf, r);
	
					if (todo == r)
					{
						if (todo2 == 0)
							goto next;
	
						todo = todo2;
						todo2 = 0;
						vec[0].buf = vec[1].buf;
					}
					else
					{
						vec[0].buf += r;
						todo -= r;
					}
				}
#ifdef HAVE_TRIPLEDRAGON
				if (r < 0 && errno != EAGAIN)
				{
					perror("[stream2file] read DMX");
					exit_flag = STREAM2FILE_STATUS_READ_FAILURE;
					break;
				}
#endif
			}
			else if (!pres){
				printf ("[stream2file]: timeout reading from demux\n");
				exit_flag = STREAM2FILE_STATUS_READ_FAILURE;
			}
		}
		next:
			todo = IN_SIZE;
	}

	if (v_arg == &dvrfd)
		close(*(int *)v_arg);
	else
		unsetPesFilter(*(int *)v_arg);

	pthread_join(file_thread, NULL);

	if (ringbuf)
		ringbuffer_free(ringbuf);

	if (v_arg == &dvrfd)
		while (demuxfd_count > 0)
			unsetPesFilter(demuxfd[--demuxfd_count]);

	DEC_BUSY_COUNT;

	if ((v_arg == &dvrfd) || (v_arg == (&(demuxfd[0]))))
	{
		CEventServer eventServer;
		eventServer.registerEvent2(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, "/tmp/neutrino.sock");
		stream2file_status2_t s;
		s.status = exit_flag;
		strncpy(s.filename,basename(myfilename),512);
		s.filename[511] = '\0';
		strncpy(s.dir,dirname(myfilename),100);
		s.dir[99] = '\0';
		eventServer.sendEvent(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, &s, sizeof(s));
		printf("[stream2file]: pthreads exit code: %i, dir: '%s', filename: '%s' myfilename: '%s'\n", exit_flag, s.dir, s.filename, myfilename);
	}

	pthread_exit(NULL);
}
Пример #9
0
void *VideoLayer::feed() {
  int got_picture=0;
  int len1=0 ;
  int ret=0;
  bool got_it=false;

  double now = get_master_clock();


  if(paused)
    return rgba_picture->data[0];

  /**
   * follow user video loop
   */
  if(mark_in!=NO_MARK && mark_out!=NO_MARK && seekable) {
    if (now >= mark_out)
      seek((int64_t)mark_in * AV_TIME_BASE);
  }
  
  // operate seek if was requested
  if(to_seek>=0) {
    seek(to_seek);
    to_seek = -1;
  }
    
  got_it=false;
  
  while (!got_it) {
    
    
    if(packet_len<=0) {
      /**
       * Read one packet from the media and put it in pkt
       */
      while(1) {
#ifdef DEBUG
	func("av_read_frame ...");
#endif
	ret = av_read_frame(avformat_context, &pkt);

#ifdef DEBUG
	if(pkt.stream_index == video_index)
	  std::cout << "video read packet";
	else if(pkt.stream_index == audio_index)
	  std::cout << "audio read packet";
	std::cout << " pkt.data=" << pkt.data;
	std::cout << " pkt.size=" << pkt.size;
	std::cout << " pkt.pts/dts=" << pkt.pts << "/" << pkt.dts << std::endl;
	std::cout << "pkt.duration=" << pkt.duration;
	std::cout << " avformat_context->start_time=" << avformat_context->start_time;
	std::cout << " avformat_context->duration=" << avformat_context->duration/AV_TIME_BASE << std::endl;
	std::cout << "avformat_context->duration=" << avformat_context->duration << std::endl;
#endif
	
	/* TODO(shammash): this may be good for streams but breaks
	 * looping in files, needs fixing. */
	// 	      if(!pkt.duration) continue;
	
	// 	      if(!pkt.size || !pkt.data) {
	// 		return NULL;
	// 	      }
	
	
	/**
	 * check eof and loop
	 */
	if(ret!= 0) {	//does not enter if data are available
	  eos->notify();
	  //	  eos->dispatcher->do_jobs(); /// XXX hack hack hack
	  ret = seek(avformat_context->start_time);
	  if (ret < 0) {
	    error("VideoLayer::could not loop file");
	    return rgba_picture->data[0];
	  }
	  continue;
	} else if( (pkt.stream_index == video_index) 
		   || (pkt.stream_index == audio_index) )
	  break; /* exit loop */
      }
    } // loop break after a known index is found
    
    
    frame_number++;
	//std::cout << "frame_number :" << frame_number << std::endl;
    
    /**
     * Decode video
     */
    if(pkt.stream_index == video_index) {
      
      len1 = decode_video_packet(&got_picture);
      
      AVFrame *yuv_picture=&av_frame;
      if(len1<0) {
	//	  error("VideoLayer::Error while decoding frame");
	func("one frame only?");
	return NULL;
      }
      else if (len1 == 0) {
	packet_len=0;
	return NULL;
      }
      
      /**
       * We've found a picture
       */
      ptr += len1;
      packet_len -= len1;
      if (got_picture!=0) {
	got_it=true;
	avformat_stream=avformat_context->streams[video_index];
	
	/** Deinterlace input if requested */
	if(deinterlaced)
	  deinterlace((AVPicture *)yuv_picture);
	
#ifdef WITH_SWSCALE
	sws_scale(img_convert_ctx, yuv_picture->data, yuv_picture->linesize,
		  0, video_codec_ctx->height,
		  rgba_picture->data, rgba_picture->linesize);	  
#else
	/**
	 * yuv2rgb
	 */
	img_convert(rgba_picture, PIX_FMT_RGB32, (AVPicture *)yuv_picture,
		    video_codec_ctx->pix_fmt, 
		    //avformat_stream.codec->pix_fmt,
		    video_codec_ctx->width,
		    video_codec_ctx->height);
#endif
	// memcpy(frame_fifo.picture[fifo_position % FIFO_SIZE]->data[0],rgba_picture->data[0],geo.size);
	/* TODO move */
	if(fifo_position == FIFO_SIZE)
	  fifo_position=0;
	
	/* workaround since sws_scale conversion from YUV
	   returns an buffer RGBA with alpha set to 0x0  */
	{
	  register int bufsize = ( rgba_picture->linesize[0] * video_codec_ctx->height ) /4;
	  int32_t *pbuf =  (int32_t*)rgba_picture->data[0];
	  
	  for(; bufsize>0; bufsize--) {
	    *pbuf = (*pbuf | alpha_bitmask);
	    pbuf++;
	  }
	} 
	
	jmemcpy(frame_fifo.picture[fifo_position]->data[0],
		rgba_picture->data[0],
		rgba_picture->linesize[0] * video_codec_ctx->height);
	
	//			    avpicture_get_size(PIX_FMT_RGBA32, enc->width, enc->height));
	fifo_position++;
      }
    } // end video packet decoding
    

    ////////////////////////
    // audio packet decoding
    else if(pkt.stream_index == audio_index) {
      // XXX(shammash): audio decoding seems to depend on screen properties, so
      //                we skip decoding audio frames if there's no screen
      //  long unsigned int m_SampleRate = screen->m_SampleRate?*(screen->m_SampleRate):48000;
      //  ringbuffer_write(screen->audio, (const char*)audio_float_buf,  samples*sizeof(float));
      //  ... and so on ...
      if(use_audio && screen) {
	int data_size;
	len1 = decode_audio_packet(&data_size);
	if (len1 > 0)  {
	  int samples = data_size/sizeof(uint16_t);
	  long unsigned int m_SampleRate = screen->m_SampleRate?*(screen->m_SampleRate):48000;
	  double m_ResampleRatio = (double)(m_SampleRate)/(double)audio_samplerate; 
	  long unsigned max_buf = ceil(AVCODEC_MAX_AUDIO_FRAME_SIZE * m_ResampleRatio * audio_channels);

	  if (audio_resampled_buf_len < max_buf) {
		if (audio_resampled_buf) free (audio_resampled_buf);
		audio_resampled_buf = (float*) malloc(max_buf * sizeof(float));
		audio_resampled_buf_len = max_buf;
	  }

	  src_short_to_float_array ((const short*) audio_buf, audio_float_buf, samples);
	  if (m_ResampleRatio == 1.0) 
	  {
	    ringbuffer_write(screen->audio, (const char*)audio_float_buf,  samples*sizeof(float));
	    time_t *tm = (time_t *)malloc(sizeof(time_t));
	    time (tm);
// 	    std::cerr << "-- VL:" << asctime(localtime(tm));
	  } 
	  else 
	  {
	    src_short_to_float_array ((const short*) audio_buf, audio_float_buf, samples);

	    SRC_DATA src_data;
	    int offset = 0;

            do {
	      src_data.input_frames  = samples/audio_channels;
	      src_data.output_frames = audio_resampled_buf_len/audio_channels - offset;
	      src_data.end_of_input  = 0;
	      src_data.src_ratio     =  m_ResampleRatio;
	      src_data.input_frames_used = 0;
	      src_data.output_frames_gen = 0;
	      src_data.data_in       = audio_float_buf + offset; 
	      src_data.data_out      = audio_resampled_buf + offset;

	      src_simple (&src_data, SRC_SINC_MEDIUM_QUALITY, audio_channels) ;
	      ringbuffer_write(screen->audio,
			       (const char*)audio_resampled_buf,
			       src_data.output_frames_gen * audio_channels *sizeof(float));

	      offset += src_data.input_frames_used * audio_channels;
	      samples -= src_data.input_frames_used * audio_channels;

	      if (samples>0)
		warning("resampling left: %i < %i",
			src_data.input_frames_used, samples/audio_channels);

	    } while (samples > audio_channels);
	  }
	}
      }
    }
    
    av_free_packet(&pkt); /* sun's good. love's bad */
    
  } // end of while(!got_it)
  
  return frame_fifo.picture[fifo_position-1]->data[0];
}
Пример #10
0
static
void
data_available_for_stream(pa_mainloop_api *a, pa_io_event *ioe, int fd, pa_io_event_flags_t events,
                          void *userdata)
{
    pa_stream          *s = userdata;
    snd_pcm_sframes_t   frame_count;
    size_t              frame_size = pa_frame_size(&s->ss);
    char                buf[16 * 1024];
    int                 paused = g_atomic_int_get(&s->paused);

    if (events & (PA_IO_EVENT_INPUT | PA_IO_EVENT_OUTPUT)) {

#if HAVE_SND_PCM_AVAIL
        frame_count = snd_pcm_avail(s->ph);
#else
        snd_pcm_hwsync(s->ph);
        frame_count = snd_pcm_avail_update(s->ph);
#endif

        if (frame_count < 0) {
            if (frame_count == -EBADFD) {
                // stream was closed
                return;
            }

            int cnt = 0, ret;
            do {
                cnt ++;
                ret = snd_pcm_recover(s->ph, frame_count, 1);
            } while (ret == -1 && errno == EINTR && cnt < 5);

#if HAVE_SND_PCM_AVAIL
            frame_count = snd_pcm_avail(s->ph);
#else
            snd_pcm_hwsync(s->ph);
            frame_count = snd_pcm_avail_update(s->ph);
#endif

            if (frame_count < 0) {
                trace_error("%s, can't recover after failed snd_pcm_avail (%d)\n", __func__,
                            (int)frame_count);
                return;
            }
        }
    } else {
        return;
    }

    if (events & PA_IO_EVENT_OUTPUT) {
        if (paused) {
            // client stream is corked. Pass silence to ALSA
            size_t bytecnt = MIN(sizeof(buf), frame_count * frame_size);
            memset(buf, 0, bytecnt);
            snd_pcm_writei(s->ph, buf, bytecnt / frame_size);
        } else {
            size_t writable_size = pa_stream_writable_size(s);

            if (s->write_cb && writable_size > 0)
                s->write_cb(s, writable_size, s->write_cb_userdata);

            size_t bytecnt = MIN(sizeof(buf), frame_count * frame_size);
            bytecnt = ringbuffer_read(s->rb, buf, bytecnt);

            if (bytecnt == 0) {
                // application is not ready yet, play silence
                bytecnt = MIN(sizeof(buf), frame_count * frame_size);
                memset(buf, 0, bytecnt);
            }
            snd_pcm_writei(s->ph, buf, bytecnt / frame_size);
        }
    }

    if (events & PA_IO_EVENT_INPUT) {
        if (paused) {
            // client stream is corked. Read data from ALSA and discard them
            size_t bytecnt = MIN(sizeof(buf), frame_count * frame_size);
            snd_pcm_readi(s->ph, buf, bytecnt / frame_size);
        } else {
            size_t bytecnt = ringbuffer_writable_size(s->rb);

            if (bytecnt == 0) {
                // ringbuffer is full because app doesn't read data fast enough.
                // Make some room
                ringbuffer_drop(s->rb, frame_count * frame_size);
                bytecnt = ringbuffer_writable_size(s->rb);
            }

            bytecnt = MIN(bytecnt, frame_count * frame_size);
            bytecnt = MIN(bytecnt, sizeof(buf));

            if (bytecnt > 0) {
                snd_pcm_readi(s->ph, buf, bytecnt / frame_size);
                ringbuffer_write(s->rb, buf, bytecnt);
            }

            size_t readable_size = pa_stream_readable_size(s);
            if (s->read_cb && readable_size > 0)
                s->read_cb(s, readable_size, s->read_cb_userdata);
        }
    }
}
Пример #11
0
int JackClient::Process(jack_nframes_t nframes, void *self) {
    int j = 0;
    bool isEncoded = ((JackClient*) self)->m_Encoded;

    for(std::map<int, JackPort*>::iterator i = m_InputPortMap.begin();
        i != m_InputPortMap.end(); i++) {
        if(jack_port_connected(i->second->Port)) {
            sample_t *in = (sample_t *) jack_port_get_buffer(i->second->Port, nframes);
//                memcpy (i->second->Buf, in, sizeof (sample_t) * m_BufferSize); //m_BufferSize -> 2nd AudioCollector parameter
            //Buff attribué par SetInputBuf dans le construcAteur de AudioCollector
            if(isEncoded) {     //Added this to write in the buffer only if
                //the encoder is in action
                if(!j) {        //only streams the 1st Jack Input port
                    if(ringbuffer_write_space(((JackClient*) self)->first) >= (sizeof(sample_t) * nframes)) {
                        ringbuffer_write(((JackClient*) self)->first, (char *)in, (sizeof(sample_t) * nframes));
                    }
                    /*		    else
                                    {
                                      std::cerr << "-----------Pas suffisament de place dans audio_fred !!!" << std::endl;
                                    }*/
                    j++;
                }
            }
        }
    }

    int channels = ((JackClient*) self)->m_ringbufferchannels;


    bool output_available = false;
//m_ringbuffer created by ViewPort::add_audio
//1024*512 rounded up to the next power of two.
    if(((JackClient*) self)->m_ringbuffer) {
//        static int firsttime = 1 + ceil(4096/nframes); // XXX pre-buffer  TODO decrease this and compensate latency

        if(ringbuffer_read_space(((JackClient*) self)->m_ringbuffer) >=
           /*firsttime */ channels * nframes * sizeof(float)) {
//                firsttime=1;
            size_t rv = ringbuffer_read(((JackClient*) self)->m_ringbuffer,
                                        ((JackClient*) self)->m_inbuf,
                                        channels * nframes * sizeof(float));
            if(isEncoded) {     //Added this to write in the buffer only if
                //the encoder is in action
                if(ringbuffer_write_space(((JackClient*) self)->audio_mix_ring) >= rv) {
//                      unsigned char *aPtr = (unsigned char *)((JackClient*) self)->m_inbuf;
                    size_t rf = ringbuffer_write(((JackClient*) self)->audio_mix_ring, ((JackClient*) self)->m_inbuf, rv);
                    if(rf != rv)
                        std::cerr << "---" << rf << " : au lieu de :" << rv << " octets ecrits dans le ringbuffer !!" \
                                  << std::endl;
                } else {
                    std::cerr << "-----------Not enough room in audio_mix_ring !!!" << std::endl;
                }
            }
//reads m_ringbuffer and puts it in m_inbuf
//m_inbuf created in SetRingbufferPtr called by add_audio
//4096 * channels * sizeof(float)
            if(rv >= channels * nframes * sizeof(float)) {
                output_available = true;
            }
        }
#if 0
        else if(firsttime == 1)
            fprintf(stderr, "AUDIO BUFFER UNDERRUN: %i samples < %i\n", ringbuffer_read_space(((JackClient*) self)->m_ringbuffer) / sizeof(float) / channels, nframes);
#endif
    }

    j = 0;
    for(std::map<int, JackPort*>::iterator i = m_OutputPortMap.begin();
        i != m_OutputPortMap.end(); i++) {
        if(output_available && j < channels) {
            sample_t *out = (sample_t *) jack_port_get_buffer(i->second->Port, nframes);
            memset(out, 0, sizeof(jack_default_audio_sample_t) * nframes);
            deinterleave(((JackClient*) self)->m_inbuf, out, channels
                         , j, nframes);
//writes nframes of channels m_inbuf to out
//two times if stereo (shifted by the channel number)
#if 0                   // test-noise:
            int i;
            for(i = 0; i < nframes; i++) out[i] = (float) i / (float)nframes;
#endif
        } else { // no output availaible, clear
            sample_t *out = (sample_t *) jack_port_get_buffer(i->second->Port, nframes);
            memset(out, 0, sizeof(sample_t) * nframes);
        }
        j++;
    }

    m_BufferSize = nframes;

//      if(RunCallback&&RunContext)
//      {
//              // do the work
//              RunCallback(RunContext, nframes);
//      }

    return 0;
}
Пример #12
0
int ilctts_pcm_write(TTSRENDER_STATE_T *st, void *data, int length) {
	return ringbuffer_write(st->ringbuffer, data, length << 1);
} // end ilctts_pcm_write