예제 #1
0
파일: amp.c 프로젝트: jun0813/libamp
AMP_Proto_T *amp_new_proto(void)
{
    AMP_Proto_T *proto;
    AMP_Box_T *box = NULL;
    _AMP_Callback_Map_p outstanding_requests = NULL;
    _AMP_Responder_Map_p responders = NULL;

    if ( (proto = MALLOC(sizeof(struct AMP_Proto))) == NULL)
        return NULL;

    proto->state = KEY_LEN_READ;
    proto->error = 0;
    if((box = amp_new_box()) == NULL)
        goto error;

    proto->last_ask_key = 0;

    proto->key_len = -1;
    proto->key_data_fetched = 0;

    proto->val_len = -1;
    proto->val_data_fetched = 0;

    proto->dispatch_box = _amp_process_full_packet;

    if ((outstanding_requests = _amp_new_callback_map()) == NULL)
        goto error;

    if((responders = _amp_new_responder_map()) == NULL)
        goto error;

    proto->box = box;
    proto->outstanding_requests = outstanding_requests;
    proto->responders = responders;

    debug_print("New AMP_Proto at 0x%p\n", proto);
    return proto;

error:
    free(proto);

    if (box)
        amp_free_box(box);

    if (outstanding_requests)
        _amp_free_callback_map(outstanding_requests);

    /* NOTE - uncomment this if new structures are allocated below
     * the line above where `responders' is allocated
    if (responders)
        _amp_free_responder_map(responders);
     */

    return NULL;
}
예제 #2
0
파일: amp.c 프로젝트: jun0813/libamp
int amp_consume_bytes(AMP_Proto_T *proto, unsigned char* buf, int len)
{
    /* Guaranteed to have at least 1 byte in `buf' */

    int idx = 0;
    int bytesConsumed = 0;
    int parseStatus;

    if (proto->error)
    {
        /* refuse to do any more work if the protocol
         * parser has previously encounted a fatal error. */
        return AMP_PROTO_ERROR;
    }

    while (idx < len) {

        parseStatus = amp_parse_box(proto, proto->box, &bytesConsumed,
                                    buf+idx, len-idx);
        idx += bytesConsumed;
        if (parseStatus)
        {
            /* got a full box */

            /* Dispatch it */
            proto->error = proto->dispatch_box(proto, proto->box);
            if (proto->error)
                return proto->error;

            /* Start parsing a new AMP box.
             * The handler function has taken ownership of the box we
             * just dispatched - so don't free it. */
            proto->box = amp_new_box();
        }
        else
        {
            /* might be error, or might have parsed partial box */
            if (proto->error)
                return proto->error;

            /* if no error it should mean that amp_parse_box()
             * consumed all of the bytes remaining in buf, and
             * we should fall out of the while-loop now */
        }
    }
    return 0;
}
예제 #3
0
파일: amp.c 프로젝트: jun0813/libamp
void amp_reset_proto(AMP_Proto_T *proto)
{
    proto->state = KEY_LEN_READ;

    proto->key_len = -1;
    proto->key_data_fetched = 0;

    proto->val_len = -1;
    proto->val_data_fetched = 0;

    /* TODO - more efficient to delete the key/values instead of freeing
     * and allocating a new box ? */
    amp_free_box(proto->box);
    proto->box = amp_new_box();

    proto->error = 0;
}
예제 #4
0
/*  
 *   Code to Send AMP message
 */
void do_sum_call(AMP_Proto_T *proto, Sum_State_T sum_state)
{
    int ret;
    AMP_Box_T *box = amp_new_box();
    amp_put_long_long(box, "a", sum_state->operands[sum_state->idx]);
    amp_put_long_long(box, "b", sum_state->operands[sum_state->idx+1]);

    sum_state->idx++;

    ret = amp_call(proto, "Sum", box, resp_cb, sum_state,
                   &(sum_state->lastAskKey));
    if (ret)
    {
        fprintf(stderr, "amp_call() failed: %s\n", amp_strerror(ret));
        exit(1);
    }
}
예제 #5
0
파일: amp.c 프로젝트: jun0813/libamp
amp_error_t _amp_send_unhandled_command_error(AMP_Proto_T *proto, AMP_Request_T *req)
{
    /* Fire off an _error box */

    AMP_Box_T *box;
    unsigned char *buf    = NULL;
    unsigned char *idx;
    unsigned char *packet = NULL;
    int packetSize;
    amp_error_t ret = 0;

    static char prefix[] = "Unhandled Command: '";
    static char suffix[] = "'";


    if ((box = amp_new_box()) == NULL)
        return ENOMEM;

    /* put _error key */
    if ((ret = amp_put_bytes(box, _ERROR, req->ask_key->value,
                             req->ask_key->size)) != 0)
        goto error;

    /* put _error_code key */
    if ((ret = amp_put_cstring(box, ERROR_CODE, AMP_ERROR_UNHANDLED)) != 0)
        goto error;

    /* put _error_description key */
    int bufSize = sizeof(prefix) + req->command->size + sizeof(suffix) - 2;
    if ((buf = MALLOC(bufSize)) == NULL)
    {
        ret = ENOMEM;
        goto error;
    }
    idx = buf;

    /* use sizeof(s)-1 instead of strlen() as cheap optimization */
    memcpy(idx, prefix, sizeof(prefix)-1);
    idx += sizeof(prefix)-1;

    memcpy(idx, req->command->value, req->command->size);
    idx += req->command->size;

    memcpy(idx, suffix, sizeof(suffix)-1);

    /* TODO - it might be handy to have an amp_put_bytes_no_copy() API
     * to avoid the copying overhead in cases such as this where the
     * box can happily take ownership of the malloc'd buffer */
    if ((ret = amp_put_bytes(box, ERROR_DESCR, buf, bufSize)) != 0)
        goto error;

    /* buf has been copied in to the box now */

    if ((ret = amp_serialize_box(box, &packet, &packetSize)) != 0)
        goto error;

    /* write handler has taken possession of buffer - don't free */
    ret = proto->write(proto, packet, packetSize, proto->write_arg);

error:
    amp_free_box(box);
    free(buf);
    return ret;
}