static int cwx_request(CWX_CONNECT* conn){ char szHead[CWINUX_MSG_HEAD_LEN + 1]; CWX_MSG_HEADER_S msg_head; CWX_KEY_VALUE_ITEM_S item; CWX_KEY_VALUE* key_value; CWX_UINT64 begin, end, now; char* pvalue; char* snd_buf=0; int buf_size = 0; int pos; int len; int ret; int http_code = OK; CWX_UINT32 delay = 0; pos = CWINUX_MSG_HEAD_LEN; buf_size = conn->m_args?strlen(conn->m_args)+ 2048:2048; snd_buf = (char*)apr_pcalloc(conn->m_request->pool, buf_size); //get ip pvalue = cwx_get_ip(conn->m_request); if (NULL == pvalue) pvalue="255.255.255.255"; //append ip if (-1 == (len = cwx_append_key(snd_buf + pos, buf_size - pos, "cwinux_ip", pvalue, strlen(pvalue), false))){ CWX_ERR(("%s:%d:cwx_request(): Failure to invoke cwx_append_key() to append cwinux_ip\n", __FILE__, __LINE__)); return HTTP_INTERNAL_SERVER_ERROR; } pos += len; //append url if (-1 == (len = cwx_append_key(snd_buf + pos, buf_size - pos, "cwinux_url", conn->m_request->uri, strlen(conn->m_request->uri), false))){ CWX_ERR(("%s:%d:cwx_request(): Failure to invoke cwx_append_key() to append cwinux_url\n", __FILE__, __LINE__)); return HTTP_INTERNAL_SERVER_ERROR; } pos += len; key_value = conn->m_args_head; while(key_value){ if ((strcmp(key_value->m_key, "cwinux_ip") != 0) && (strcmp(key_value->m_key, "cwinux_url") != 0)){ //append arg if (-1 == (len = cwx_append_key(snd_buf + pos, buf_size - pos, key_value->m_key, key_value->m_value, strlen(key_value->m_value), false))){ CWX_ERR(("%s:%d:cwx_request(): Failure to invoke cwx_append_key() to append arg key\n", __FILE__, __LINE__)); return HTTP_INTERNAL_SERVER_ERROR; } pos += len; } key_value = key_value->m_next; } msg_head.m_ucAttr = 0; msg_head.m_ucVersion = 0; msg_head.m_uiDataLen = pos - CWINUX_MSG_HEAD_LEN; msg_head.m_uiTaskId = 0; msg_head.m_unMsgType = atoi(conn->m_msg_type); cwx_pack_head(&msg_head, snd_buf); //send msg begin = (CWX_UINT64)conn->m_request->request_time/1000; end = begin + conn->m_host->m_user_config.m_query_timeout; now = cwx_time_of_day()/1000; if (now >= end) return HTTP_REQUEST_TIME_OUT; ret = cwx_stream_write(conn, snd_buf, pos, (CWX_UINT32)(end - now)); if (-1 == ret){ cwx_stream_close(conn->m_socket->m_fd); conn->m_socket->m_fd = -1; return HTTP_PRECONDITION_FAILED; }else if(0 == ret){ cwx_stream_close(conn->m_socket->m_fd); conn->m_socket->m_fd = -1; return HTTP_REQUEST_TIME_OUT; } //recv msg in following //recv head first now = cwx_time_of_day()/1000; if (now >= end) return HTTP_REQUEST_TIME_OUT; ret = cwx_stream_read(conn, szHead, CWINUX_MSG_HEAD_LEN, end - now); if (-1 == ret){ cwx_stream_close(conn->m_socket->m_fd); conn->m_socket->m_fd = -1; return HTTP_BAD_REQUEST; }else if(0 == ret){ cwx_stream_close(conn->m_socket->m_fd); conn->m_socket->m_fd = -1; return HTTP_REQUEST_TIME_OUT; } if (!cwx_unpack_head(szHead, &msg_head)){ cwx_stream_close(conn->m_socket->m_fd); conn->m_socket->m_fd = -1; CWX_ERR(("%s:%d:cwx_request(): Failure to invoke cwx_unpack_head().\n", __FILE__, __LINE__)); return HTTP_INTERNAL_SERVER_ERROR; } if (msg_head.m_unMsgType != atoi(conn->m_msg_type) + 1){ cwx_stream_close(conn->m_socket->m_fd); conn->m_socket->m_fd = -1; CWX_ERR(("%s:%d:cwx_request(): Reply msg type error. should be %d, but:%d. handle=%s, arg=%s\n", __FILE__, __LINE__, atoi(conn->m_msg_type) + 1, msg_head.m_unMsgType, conn->m_request->handler, conn->m_args?conn->m_args:"")); return HTTP_INTERNAL_SERVER_ERROR; } //recv data char* recv_buf = (char*)apr_pcalloc(conn->m_request->pool, msg_head.m_uiDataLen); now = cwx_time_of_day()/1000; if (now >= end) return HTTP_REQUEST_TIME_OUT; ret = cwx_stream_read(conn, recv_buf, msg_head.m_uiDataLen, end-now); if (-1 == ret){ cwx_stream_close(conn->m_socket->m_fd); conn->m_socket->m_fd = -1; return HTTP_PRECONDITION_FAILED; }else if(0 == ret){ cwx_stream_close(conn->m_socket->m_fd); conn->m_socket->m_fd = -1; return HTTP_REQUEST_TIME_OUT; } now = cwx_time_of_day()/1000; delay = now - (CWX_UINT64)conn->m_request->request_time/1000; if (1 != conn->m_host->m_user_config.m_show){ //get code ret = cwx_get_key_by_name(recv_buf, msg_head.m_uiDataLen, "code", &item); if (0>ret){ CWX_ERR(("%s:%d:cwx_request(): handle=[%s] Failure to invoke cwx_get_key_by_name(\"code\").\n", __FILE__, __LINE__, conn->m_request->handler)); return HTTP_INTERNAL_SERVER_ERROR; }else if (0 == ret){ CWX_ERR(("%s:%d:cwx_request(): handle=[%s] no [code] key in reply package.\n", __FILE__, __LINE__, conn->m_request->handler)); return HTTP_INTERNAL_SERVER_ERROR; } ret = atoi(item.m_szData); if (0 > ret){ http_code = HTTP_BAD_REQUEST; }else if (200 > ret){ http_code = OK; } if (OK != http_code){ CWX_ERR(("%s:%d:cwx_request(): handle=[%s] Query failure, code=%d.\n", __FILE__, __LINE__, conn->m_request->handler, ret)); } //get content-type ret = cwx_get_key_by_name(recv_buf, msg_head.m_uiDataLen, "content-type", &item); if (ret>0){ conn->m_request->content_type = item.m_szData; } //get content ret = cwx_get_key_by_name(recv_buf, msg_head.m_uiDataLen, "content", &item); if (0>ret){ CWX_ERR(("%s:%d:cwx_request(): handle=[%s] Failure to invoke cwx_get_key_by_name(\"content\").\n", __FILE__, __LINE__, conn->m_request->handler)); return HTTP_INTERNAL_SERVER_ERROR; }else if (0 == ret){ CWX_ERR(("%s:%d:cwx_request(): handle=[%s] no [content] key in reply package.\n", __FILE__, __LINE__, conn->m_request->handler)); return HTTP_INTERNAL_SERVER_ERROR; } cwx_output_header(conn, delay); ap_rwrite(item.m_szData, item.m_uiDataLen, conn->m_request); return http_code; } //show the package if (!cwx_is_valid_package(recv_buf, msg_head.m_uiDataLen)){ cwx_output_header(conn, delay); ap_rwrite(recv_buf, msg_head.m_uiDataLen, conn->m_request); return http_code; } char* out_buf = (char*)apr_pcalloc(conn->m_request->pool, msg_head.m_uiDataLen * 2); CWX_UINT32 data_size = 0; len = 0; while(len < msg_head.m_uiDataLen){ if (0>= cwx_get_key_by_index(recv_buf + len, msg_head.m_uiDataLen - len, 0, &item)) break; memcpy(out_buf +data_size, item.m_szKey, item.m_unKeyLen); data_size+=item.m_unKeyLen; memcpy(out_buf +data_size, "=", 1); data_size+=1; memcpy(out_buf +data_size, item.m_szData, item.m_uiDataLen); data_size+=item.m_uiDataLen; memcpy(out_buf +data_size, "\n", 1); data_size+=1; len += cwx_get_kv_len(item.m_unKeyLen, item.m_uiDataLen); } out_buf[data_size]=0x00; cwx_output_header(conn, delay); ap_rwrite(out_buf, data_size, conn->m_request); return http_code; }
static ngx_int_t ngx_http_cwinux_process_header(ngx_http_request_t *r) { ngx_http_upstream_t *u; ngx_http_cwinux_ctx_t *ctx; ngx_http_cwinux_loc_conf_t *mlcf; size_t recv_data_len; size_t left_data_len; size_t copy_data_len; size_t len; int http_code = 200; CWX_KEY_VALUE_ITEM_S item; int ret; u = r->upstream; mlcf = ngx_http_get_module_loc_conf(r, ngx_http_cwinux_module); ctx = ngx_http_get_module_ctx(r, ngx_http_cwinux_module); if (!ctx->header){ if (u->buffer.last - u->buffer.pos <CWINUX_MSG_HEAD_LEN){ return NGX_AGAIN; } if (!cwx_unpack_head((char*)u->buffer.pos, &ctx->msg_head)){ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "service sent invalid header"); return NGX_HTTP_UPSTREAM_INVALID_HEADER; } ctx->header = true; ctx->recv_pos = 0; ctx->data = ngx_palloc(r->pool, ctx->msg_head.m_uiDataLen); recv_data_len = u->buffer.last - u->buffer.pos - CWINUX_MSG_HEAD_LEN; left_data_len = ctx->msg_head.m_uiDataLen - ctx->recv_pos; copy_data_len = left_data_len > recv_data_len?recv_data_len:left_data_len; if (left_data_len && recv_data_len){ memcpy(ctx->data + ctx->recv_pos, u->buffer.pos + CWINUX_MSG_HEAD_LEN, copy_data_len); ctx->recv_pos += copy_data_len; } u->buffer.last = 0; if (ctx->recv_pos < ctx->msg_head.m_uiDataLen) return NGX_AGAIN; }else{ recv_data_len = u->buffer.last - u->buffer.pos; left_data_len = ctx->msg_head.m_uiDataLen - ctx->recv_pos; copy_data_len = left_data_len >recv_data_len?recv_data_len:left_data_len; memcpy(ctx->data + ctx->recv_pos, u->buffer.pos, copy_data_len); ctx->recv_pos += copy_data_len; u->buffer.last = 0; if (ctx->recv_pos < ctx->msg_head.m_uiDataLen) return NGX_AGAIN; } ctx->request->headers_out.content_type=mlcf->content_type; ctx->request->headers_out.content_type_len=mlcf->content_type.len; if (mlcf->show){ //show the package if (!cwx_is_valid_package(ctx->data, ctx->msg_head.m_uiDataLen)){ ctx->out_buf = ctx->data; ctx->out_buf_len = ctx->msg_head.m_uiDataLen; }else{ ctx->out_buf = ngx_palloc(ctx->request->pool, ctx->msg_head.m_uiDataLen * 2); ctx->out_buf_len = 0; len = 0; while(len < ctx->msg_head.m_uiDataLen){ if (0>= cwx_get_key_by_index(ctx->data + len, ctx->msg_head.m_uiDataLen - len, 0, &item)) break; memcpy(ctx->out_buf + ctx->out_buf_len, item.m_szKey, item.m_unKeyLen); ctx->out_buf_len+=item.m_unKeyLen; ctx->out_buf[ctx->out_buf_len++] = '\n'; ctx->out_buf_len += sprintf(ctx->out_buf+ctx->out_buf_len, "%u\n", item.m_uiDataLen); memcpy(ctx->out_buf + ctx->out_buf_len, item.m_szData, item.m_uiDataLen); ctx->out_buf_len+=item.m_uiDataLen; ctx->out_buf[ctx->out_buf_len++] = '\n'; len += cwx_get_kv_len(item.m_unKeyLen, item.m_uiDataLen); } ctx->out_buf[ctx->out_buf_len]=0x00; } }else{ ctx->out_buf = " "; ctx->out_buf_len = 1; //get code ret = cwx_get_key_by_name(ctx->data, ctx->msg_head.m_uiDataLen, "code", &item); if (0>ret){ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, " Failure to invoke cwx_get_key_by_name(code)"); return NGX_HTTP_UPSTREAM_FT_INVALID_HEADER; }else if (0 == ret){ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, " no [code] key in reply package."); return NGX_HTTP_UPSTREAM_FT_INVALID_HEADER; } ret = atoi(item.m_szData); if (0 > ret){ http_code = NGX_HTTP_BAD_REQUEST; }else if (200 > ret){ http_code = NGX_HTTP_OK; } if (NGX_HTTP_OK != http_code){ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, " Query failure, code=%d.", ret); } //get content-type ret = cwx_get_key_by_name(ctx->data, ctx->msg_head.m_uiDataLen, "content-type", &item); if (ret>0){ ctx->request->headers_out.content_type.data=ngx_palloc(ctx->request->pool,item.m_uiDataLen); memcpy(ctx->request->headers_out.content_type.data, item.m_szData, item.m_uiDataLen); ctx->request->headers_out.content_type.len=item.m_uiDataLen; ctx->request->headers_out.content_type_len=item.m_uiDataLen; } //get content ret = cwx_get_key_by_name(ctx->data, ctx->msg_head.m_uiDataLen, "content", &item); if (0>ret){ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, " Failure to invoke cwx_get_key_by_name(content)"); return NGX_HTTP_UPSTREAM_FT_INVALID_HEADER; }else if (0 == ret){ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, " no [content] key in reply package."); return NGX_HTTP_UPSTREAM_FT_INVALID_HEADER; } ctx->out_buf = ngx_palloc(ctx->request->pool, item.m_uiDataLen); memcpy(ctx->out_buf, item.m_szData, item.m_uiDataLen); ctx->out_buf_len = item.m_uiDataLen; } if (mlcf->delay){ struct timeval tp; ngx_gettimeofday(&tp); size_t delay= (tp.tv_sec - ctx->start_time.tv_sec)*1000 + (tp.tv_usec - ctx->start_time.tv_usec)/1000; ngx_table_elt_t *h; h = ngx_list_push(&u->headers_in.headers); if (h) { char szBuf[32]; sprintf(szBuf, "%u", delay); h->key.len = strlen("cwinux_delay"); h->key.data = (u_char*)"cwinux_delay"; h->value.len = strlen(szBuf); h->value.data = ngx_palloc(ctx->request->pool, h->value.len + 1); strcpy((char*)h->value.data, szBuf); h->lowcase_key = h->key.data; } } r->headers_out.content_length_n = ctx->out_buf_len; r->headers_out.content_length_n = ctx->out_buf_len; u->headers_in.status_n = http_code; u->state->status = http_code; return NGX_OK; }