1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#include "proxy.h"
int mcplib_response_elapsed(lua_State *L) {
mcp_resp_t *r = luaL_checkudata(L, -1, "mcp.response");
lua_pushinteger(L, r->elapsed);
return 1;
}
// resp:ok()
int mcplib_response_ok(lua_State *L) {
mcp_resp_t *r = luaL_checkudata(L, -1, "mcp.response");
if (r->status == MCMC_OK) {
lua_pushboolean(L, 1);
} else {
lua_pushboolean(L, 0);
}
return 1;
}
int mcplib_response_hit(lua_State *L) {
mcp_resp_t *r = luaL_checkudata(L, -1, "mcp.response");
if (r->status == MCMC_OK && r->resp.code != MCMC_CODE_END) {
lua_pushboolean(L, 1);
} else {
lua_pushboolean(L, 0);
}
return 1;
}
// Caller needs to discern if a vlen is 0 because of a failed response or an
// OK response that was actually zero. So we always return an integer value
// here.
int mcplib_response_vlen(lua_State *L) {
mcp_resp_t *r = luaL_checkudata(L, -1, "mcp.response");
// We do remove the "\r\n" from the value length, so if you're actually
// processing the value nothing breaks.
if (r->resp.vlen >= 2) {
lua_pushinteger(L, r->resp.vlen-2);
} else {
lua_pushinteger(L, 0);
}
return 1;
}
// Refer to MCMC_CODE_* defines.
int mcplib_response_code(lua_State *L) {
mcp_resp_t *r = luaL_checkudata(L, -1, "mcp.response");
lua_pushinteger(L, r->resp.code);
return 1;
}
// Get the unparsed response line for handling in lua.
int mcplib_response_line(lua_State *L) {
mcp_resp_t *r = luaL_checkudata(L, -1, "mcp.response");
if (r->resp.rline != NULL) {
lua_pushlstring(L, r->resp.rline, r->resp.rlen);
} else {
lua_pushnil(L);
}
return 1;
}
int mcplib_response_flag_blank(lua_State *L) {
mcp_resp_t *r = luaL_checkudata(L, 1, "mcp.response");
mcmc_resp_t reresp;
size_t len = 0;
const char *flagstr = luaL_checklstring(L, 2, &len);
if (len != 1) {
proxy_lua_error(L, "request: meta flag must be a single character");
return 0;
}
if (flagstr[0] < 65 || flagstr[0] > 122) {
proxy_lua_error(L, "request: invalid flag, must be A-Z,a-z");
return 0;
}
mcmc_parse_buf(r->buf, r->blen, &reresp);
if (reresp.type == MCMC_RESP_META) {
// r->resp.rline is the start of the meta line... rlen is the length.
// we cast away the const and do evil here.
char *pos = (char *) reresp.rline;
size_t rlen = reresp.rlen;
char *end = pos + rlen;
char flag = flagstr[0];
while (pos != end) {
// either flag is at the start of the line or it has a space
// immediately before it.
if (*pos == flag && (pos == reresp.rline || *(pos-1) == ' ')) {
while (pos != end && !isspace(*pos)) {
*pos = ' ';
pos++;
}
lua_pushboolean(L, 1); // found and blanked.
return 1;
} else {
pos++;
}
}
// TODO: blank out r->tok?
}
lua_pushboolean(L, 0); // not found or not done.
return 1;
}
void mcp_response_cleanup(LIBEVENT_THREAD *t, mcp_resp_t *r) {
// On error/similar we might be holding the read buffer.
// If the buf is handed off to mc_resp for return, this pointer is NULL
if (r->buf != NULL) {
pthread_mutex_lock(&t->proxy_limit_lock);
t->proxy_buffer_memory_used -= r->blen + r->extra;
pthread_mutex_unlock(&t->proxy_limit_lock);
free(r->buf);
r->buf = NULL;
}
r->tok.ntokens = 0;
// release our temporary mc_resp sub-object.
if (r->cresp != NULL) {
mc_resp *cresp = r->cresp;
assert(r->thread != NULL);
if (cresp->item) {
item_remove(cresp->item);
cresp->item = NULL;
}
resp_free(r->thread, cresp);
r->cresp = NULL;
}
}
int mcplib_response_gc(lua_State *L) {
LIBEVENT_THREAD *t = PROXY_GET_THR(L);
mcp_resp_t *r = luaL_checkudata(L, -1, "mcp.response");
mcp_response_cleanup(t, r);
return 0;
}
// Note that this can be called multiple times for a single object, as opposed
// to _gc. The cleanup routine is armored against repeat accesses by NULL'ing
// th efields it checks.
int mcplib_response_close(lua_State *L) {
LIBEVENT_THREAD *t = PROXY_GET_THR(L);
mcp_resp_t *r = luaL_checkudata(L, 1, "mcp.response");
mcp_response_cleanup(t, r);
return 0;
}
|