Пример #1
0
static void fifo_close_async( struct mi_root *mi_rpl, struct mi_handler *hdl,
                              int done)
{
    FILE *reply_stream;
    char *name;

    name = (char*)hdl->param;

    if ( mi_rpl!=0 || done ) {
        /*open fifo reply*/
        reply_stream = mi_open_reply_pipe( name );
        if (reply_stream==NULL) {
            LM_ERR("cannot open reply pipe %s\n", name );
            return;
        }

        if (mi_rpl!=0) {
            mi_write_tree( reply_stream, mi_rpl);
            free_mi_tree( mi_rpl );
        } else {
            mi_fifo_reply( reply_stream, "500 command failed\n");
        }

        fclose(reply_stream);
    }

    if (done)
        free_async_handler( hdl );
    return;
}
Пример #2
0
static int recur_write_tree(FILE *stream, struct mi_node *tree, str *buf,
																	int level)
{
	for( ; tree ; tree=tree->next ) {
		if (!(tree->flags & MI_WRITTEN)) {
			if (mi_write_node( buf, tree, level)!=0) {
				/* buffer is full -> write it and reset buffer */
				if (mi_fifo_reply( stream,"%.*s", buf->s-mi_write_buffer,
				mi_write_buffer)!=0)
					return -1;
				buf->s = mi_write_buffer;
				buf->len = mi_write_buffer_len;
				if (mi_write_node( buf, tree, level)!=0) {
					LM_ERR("failed to write - line too long!\n");
					return -1;
				}
			}
		}
		if (tree->kids) {
			if (recur_write_tree(stream, tree->kids, buf, level+1)<0)
				return -1;
		}
	}
	return 0;
}
Пример #3
0
static int recur_flush_tree(FILE *stream, struct mi_node *tree, str *buf,
																	int level)
{
	struct mi_node *kid, *tmp;
	int ret;

	for(kid = tree->kids ; kid ; ){
		/* write the current kid */
		if (!(kid->flags & MI_WRITTEN)){
			if (mi_write_node( buf, kid, level)!=0) {
				/* buffer is full -> write it and reset buffer */
				if (mi_fifo_reply( stream,"%.*s", buf->s-mi_write_buffer,
					mi_write_buffer)!=0)
					return -1;
				buf->s = mi_write_buffer;
				buf->len = mi_write_buffer_len;
				if (mi_write_node( buf, kid, level)!=0) {
					LM_ERR("failed to write - line too long!\n");
					return -1;
				}
			}

			/* we are sure that this node has been written
			* => avoid writing it again */
			kid->flags |= MI_WRITTEN;
		}

		/* write the current kid's children */
		if ((ret = recur_flush_tree(stream, kid, buf, level+1))<0)
			return -1;
		else if (ret > 0)
			return ret;

		if (!(kid->flags & MI_NOT_COMPLETED)){
			tmp = kid;
			kid = kid->next;
			tree->kids = kid;

			if(!tmp->kids){
				/* this node does not have any kids */
				free_mi_node(tmp);
			}
		}
		else{
			/* the node will have more kids => to keep the tree shape, do not
			 * flush any other node for now */
			return 1;
		}
	}

	return 0;
}
Пример #4
0
int mi_flush_tree(FILE *stream, struct mi_root *tree)
{
	str buf;
	str code;

	buf.s = mi_write_buffer;
	buf.len = mi_write_buffer_len;

	if (!(tree->node.flags & MI_WRITTEN)) {
		/* write the root node */
		code.s = int2str((unsigned long)tree->code, &code.len);
		if (code.len+tree->reason.len+1>buf.len) {
			LM_ERR("failed to write - reason too long!\n");
			return -1;
		}
		memcpy( buf.s, code.s, code.len);
		buf.s += code.len;
		*(buf.s++) = ' ';
		if (tree->reason.len) {
			memcpy( buf.s, tree->reason.s, tree->reason.len);
			buf.s += tree->reason.len;
		}
		*(buf.s++) = '\n';
		buf.len -= code.len + 1 + tree->reason.len+1;

		/* we are sure that this node has been written
		 * => avoid writing it again */
		tree->node.flags |= MI_WRITTEN;
	}

	if (recur_flush_tree(stream, &tree->node, &buf, 0)<0)
		return -1;

	if (buf.len<=0) {
		LM_ERR("failed to write - EOC does not fit in!\n");
		return -1;
	}
	*(buf.s++)='\n';
	buf.len--;

	if (mi_fifo_reply(stream,"%.*s",buf.s-mi_write_buffer,mi_write_buffer)!=0)
		return -1;

	return 0;
}
Пример #5
0
void mi_fifo_server(FILE *fifo_stream)
{
    struct mi_root *mi_cmd;
    struct mi_root *mi_rpl;
    struct mi_handler *hdl;
    int line_len;
    char *file_sep, *command, *file;
    struct mi_cmd *f;
    FILE *reply_stream;

    while(1) {
        reply_stream = NULL;

        /* commands must look this way ':<command>:[filename]' */
        if (mi_read_line(mi_buf,MAX_MI_FIFO_BUFFER,fifo_stream, &line_len)) {
            LM_ERR("failed to read command\n");
            continue;
        }

        /* trim from right */
        while(line_len) {
            if(mi_buf[line_len-1]=='\n' || mi_buf[line_len-1]=='\r'
                    || mi_buf[line_len-1]==' ' || mi_buf[line_len-1]=='\t' ) {
                line_len--;
                mi_buf[line_len]=0;
            } else break;
        }

        if (line_len==0) {
            LM_DBG("command empty\n");
            continue;
        }
        if (line_len<3) {
            LM_ERR("command must have at least 3 chars\n");
            continue;
        }
        if (*mi_buf!=MI_CMD_SEPARATOR) {
            LM_ERR("command must begin with %c: %.*s\n", MI_CMD_SEPARATOR, line_len, mi_buf );
            goto consume1;
        }
        command = mi_buf+1;
        file_sep=strchr(command, MI_CMD_SEPARATOR );
        if (file_sep==NULL) {
            LM_ERR("file separator missing\n");
            goto consume1;
        }
        if (file_sep==command) {
            LM_ERR("empty command\n");
            goto consume1;
        }
        if (*(file_sep+1)==0) {
            file = NULL;
        } else {
            file = file_sep+1;
            file = get_reply_filename(file, mi_buf+line_len-file);
            if (file==NULL) {
                LM_ERR("trimming filename\n");
                goto consume1;
            }
        }
        /* make command zero-terminated */
        *file_sep=0;

        f=lookup_mi_cmd( command, strlen(command) );
        if (f==0) {
            LM_ERR("command %s is not available\n", command);
            mi_open_reply( file, reply_stream, consume1);
            mi_fifo_reply( reply_stream, "500 command '%s' not available\n",
                           command);
            goto consume2;
        }

        /* if asyncron cmd, build the async handler */
        if (f->flags&MI_ASYNC_RPL_FLAG) {
            hdl = build_async_handler( file, strlen(file) );
            if (hdl==0) {
                LM_ERR("failed to build async handler\n");
                mi_open_reply( file, reply_stream, consume1);
                mi_fifo_reply( reply_stream, "500 Internal server error\n");
                goto consume2;
            }
        } else {
            hdl = 0;
            mi_open_reply( file, reply_stream, consume1);
        }

        if (f->flags&MI_NO_INPUT_FLAG) {
            mi_cmd = 0;
            mi_do_consume();
        } else {
            mi_cmd = mi_parse_tree(fifo_stream);
            if (mi_cmd==NULL) {
                LM_ERR("error parsing MI tree\n");
                if (!reply_stream)
                    mi_open_reply( file, reply_stream, consume3);
                mi_fifo_reply( reply_stream, "400 parse error in "
                               "command '%s'\n", command);
                goto consume3;
            }
            mi_cmd->async_hdl = hdl;
        }

        LM_DBG("done parsing the mi tree\n");

        if ( (mi_rpl=run_mi_cmd(f, mi_cmd,
                                (mi_flush_f *)mi_flush_tree, reply_stream))==0 ) {
            if (!reply_stream)
                mi_open_reply( file, reply_stream, failure);
            mi_fifo_reply(reply_stream, "500 command '%s' failed\n", command);
            LM_ERR("command (%s) processing failed\n", command );
        } else if (mi_rpl!=MI_ROOT_ASYNC_RPL) {
            if (!reply_stream)
                mi_open_reply( file, reply_stream, failure);
            mi_write_tree( reply_stream, mi_rpl);
            free_mi_tree( mi_rpl );
        } else {
            if (mi_cmd) free_mi_tree( mi_cmd );
            continue;
        }

        free_async_handler(hdl);
        /* close reply fifo */
        fclose(reply_stream);
        /* destroy request tree */
        if (mi_cmd) free_mi_tree( mi_cmd );
        continue;

failure:
        free_async_handler(hdl);
        /* destroy request tree */
        if (mi_cmd) free_mi_tree( mi_cmd );
        /* destroy the reply tree */
        if (mi_rpl) free_mi_tree(mi_rpl);
        continue;

consume3:
        free_async_handler(hdl);
        if (reply_stream)
consume2:
            fclose(reply_stream);
consume1:
        mi_do_consume();
    }
}