149 lines
3.7 KiB
C
149 lines
3.7 KiB
C
|
/*
|
||
|
* rpc_request.c
|
||
|
*
|
||
|
* Created on: 2011-3-21
|
||
|
* Author: yanghu
|
||
|
*/
|
||
|
|
||
|
#include "rpc_response.h"
|
||
|
#include "rpc_conn.h"
|
||
|
#include "rpc_array.h"
|
||
|
#include "rpc_util.h"
|
||
|
#include <assert.h>
|
||
|
|
||
|
static pthread_mutex_t freelock = PTHREAD_MUTEX_INITIALIZER;
|
||
|
|
||
|
static rpc_array *rpc_response_freelist = NULL;
|
||
|
|
||
|
rpc_response* rpc_response_new() {
|
||
|
if (rpc_response_freelist == NULL) {
|
||
|
pthread_mutex_lock(&freelock);
|
||
|
if (rpc_response_freelist == NULL) {
|
||
|
rpc_response_freelist = rpc_array_new();
|
||
|
}
|
||
|
pthread_mutex_unlock(&freelock);
|
||
|
}
|
||
|
//rpc_response *rsp = g_new(rpc_response,1);
|
||
|
rpc_response *rsp = (rpc_response*) rpc_array_get(rpc_response_freelist);
|
||
|
if (rsp == NULL) {
|
||
|
rsp = rpc_new(rpc_response,1);
|
||
|
}
|
||
|
return rsp;
|
||
|
}
|
||
|
|
||
|
void rpc_response_free(rpc_response *rsp) {
|
||
|
memset(rsp, 0, sizeof(rpc_response));
|
||
|
if (!rpc_array_add(rpc_response_freelist, rsp)) {
|
||
|
rpc_free(rsp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
rpc_response* rpc_response_copy_head(rpc_response *rsp) {
|
||
|
rpc_response *rsp_new = rpc_response_new();
|
||
|
rsp_new->code = rsp->code;
|
||
|
rsp_new->seq = rsp->seq;
|
||
|
rsp_new->data = rsp->data;
|
||
|
rsp_new->output_len = rsp->output_len;
|
||
|
rsp_new->phrase = strdup(rsp->phrase);
|
||
|
return rsp_new;
|
||
|
}
|
||
|
|
||
|
rpc_parse_result rpc_response_parse(rpc_conn *c, rpc_response **rsp) {
|
||
|
//request line
|
||
|
char *el, *cont;
|
||
|
int avail, num;
|
||
|
rpc_response *response = NULL;
|
||
|
el = memchr(c->rcurr, '\n', c->rbytes);
|
||
|
avail = c->rbytes;
|
||
|
if (el) {
|
||
|
cont = el + 1;
|
||
|
avail -= (cont - c->rcurr);
|
||
|
//windows newline separate is \r\n
|
||
|
if ((el - c->rcurr) > 1 && *(el - 1) == '\r') {
|
||
|
el--;
|
||
|
}
|
||
|
*el = '\0';
|
||
|
token_t tokens[3];
|
||
|
int n = tokenize_command(c->rcurr, tokens, 3);
|
||
|
if (n != 3 && strcmp(tokens[0].value, RPC_VERSION) != 0) {
|
||
|
fprintf(stderr, "status line begin error!\n");
|
||
|
return RPC_Parse_Error;
|
||
|
}
|
||
|
response = rpc_response_new();
|
||
|
response->code = (int) strtol(tokens[1].value, NULL, 10);
|
||
|
response->phrase = tokens[2].value;
|
||
|
c->rcurr = cont;
|
||
|
c->rbytes = avail;
|
||
|
} else {
|
||
|
fprintf(stderr, "not status line error!\n");
|
||
|
return RPC_Parse_Error;
|
||
|
}
|
||
|
//seq
|
||
|
el = memchr(c->rcurr, '\n', avail);
|
||
|
if (el) {
|
||
|
cont = el + 1;
|
||
|
avail -= (cont - c->rcurr);
|
||
|
if ((el - c->rcurr) > 1 && *(el - 1) == '\r') {
|
||
|
el--;
|
||
|
}
|
||
|
*el = '\0';
|
||
|
num = sscanf(c->rcurr, "seq:%d", &response->seq);
|
||
|
c->rcurr = cont;
|
||
|
c->rbytes = avail;
|
||
|
if (num != 1) {
|
||
|
rpc_response_free(response);
|
||
|
fprintf(stderr, "seq parse error!\n");
|
||
|
return RPC_Parse_Error;
|
||
|
}
|
||
|
} else {
|
||
|
rpc_response_free(response);
|
||
|
fprintf(stderr, "not seq line error!\n");
|
||
|
return RPC_Parse_Error;
|
||
|
}
|
||
|
//body len
|
||
|
el = memchr(c->rcurr, '\n', avail);
|
||
|
if (el) {
|
||
|
cont = el + 1;
|
||
|
avail -= (cont - c->rcurr);
|
||
|
if ((el - c->rcurr) > 1 && *(el - 1) == '\r') {
|
||
|
el--;
|
||
|
}
|
||
|
*el = '\0';
|
||
|
num = sscanf(c->rcurr, "body-len:%d", &response->output_len);
|
||
|
c->rcurr = cont;
|
||
|
c->rbytes = avail;
|
||
|
if (num != 1) {
|
||
|
rpc_response_free(response);
|
||
|
fprintf(stderr, "body-len line parse error!\n");
|
||
|
return RPC_Parse_Error;
|
||
|
}
|
||
|
} else {
|
||
|
rpc_response_free(response);
|
||
|
fprintf(stderr, "not body-len line error!\n");
|
||
|
return RPC_Parse_Error;
|
||
|
}
|
||
|
//new line
|
||
|
el = memchr(c->rcurr, '\n', avail);
|
||
|
if (el) {
|
||
|
cont = el + 1;
|
||
|
avail -= (cont - c->rcurr);
|
||
|
if ((el - c->rcurr == 0) || ((el - c->rcurr) == 1 && *(el - 1) == '\r')) {
|
||
|
if (avail >= response->output_len) {
|
||
|
response->output = cont;
|
||
|
c->rcurr = cont + response->output_len;
|
||
|
c->rbytes = avail - response->output_len;
|
||
|
*rsp = response;
|
||
|
return RPC_Parse_OK;
|
||
|
} else {
|
||
|
c->rcurr = cont;
|
||
|
c->rbytes = avail;
|
||
|
*rsp = response;
|
||
|
return RPC_Parse_NeedData;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
fprintf(stderr, "body error!\n");
|
||
|
rpc_response_free(response);
|
||
|
return RPC_Parse_Error;
|
||
|
}
|