Exemplo n.º 1
0
void WorkerThread::TcpConnReadCb(bufferevent * bev,void *ctx){
    unsigned int sessionid=*(static_cast<unsigned int *>(ctx));
    // std::shared_ptr<TcpConnItem> ptci=std::shared_ptr<TcpConnItem>(ctx);
    std::shared_ptr<TcpConnItem> ptci=pthread_info->FindTcpConnItem(sessionid);
        struct evbuffer * in=bufferevent_get_input(bev);
        struct evbuffer * out=bufferevent_get_output(bev);

        unsigned char ch[10]={0};
        unsigned short len=0;
        if(ptci->packettype!=TCPTERMINAL){
            if(ptci->HasRemaining())
                {
                        if(!ptci->AllocateCopyData(in)){
                                LOG(WARNING)<<"AllocateCopyData failed";
                                ptci->FreeData();
                        }

                        //has received an complete packet
                        if(!ptci->HasRemaining()){
                            TcpConnItemData data(ptci,ptci->data,ptci->totallength);
                            ptci->ReleaseDataOwnership();//释放所有权
                            std::shared_ptr<ThreadPoolMethod> method=pthread_info->ls_->map_thread_pool_method_["dxpupload"];
                            (*method)(data);
                        }
                }
                else{
                        if(evbuffer_copyout(in,ch,4)!=-1)
                        {
                                if(ch[0]==0x55){//DXP PROTOCOL
                                        uint8_t lsb=ch[2];
                                        uint8_t msb=0;
                                        if(lsb&0x01)
                                                msb=ch[3];

                                        lsb=lsb>>1;
                                        unsigned short len=lsb+msb*128;
                                        if(len>127)
                                                len+=4;
                                        else
                                                len+=3;

                                        len=lsb+msb*128;

                                        unsigned short occupied=0;

                                        if(len>127)
                                                len+=4;
                                        else
                                                len+=3;

                                        // ptci->SetProtocol(DXP);
                                }
                                else{//other protocols
                                        // ptci->SetProtocol(UNKNOWN);
                                }

                                if(!ptci->AllocateCopyData(in,len)){
                                        LOG(WARNING)<<"AllocateCopyData failed";
                                        ptci->FreeData();
                                }

                        }else{
// Process a request
// Call the default callback when a uri isn't found
void process_request(struct evhttp_request *req, void *arg) {
  // Form a Request object from the evhttp request data, and call the
  // appropriate callback.  Then, we return a string in the callback that's
  // sent in the response, and check the error object stored within the
  // request pointer passed into the method

  Request *r = new Request();
  RequestError *err = r->req_err;
  const char * uri_cstr = evhttp_request_uri(req);
  std::string uri(uri_cstr);
  r->req_addr = uri;

  // Get the data out of the evhttp request buffer
  try {
    size_t len = evbuffer_get_length(evhttp_request_get_input_buffer(req));
    struct evbuffer *in_evb = evhttp_request_get_input_buffer(req);
    char *data = (char*)malloc(len);
    evbuffer_copyout(in_evb, data, len);

    // Put the data into the universal request struct
    std::string rdata(data, len);
    r->req_data = rdata;
    free(data);
  }
  catch (std::exception& e) {
    err->err_code = HTTP_BADREQUEST;
    err->err_message = e.what();
  }

  // Determine the Request type
  if (req->type == 1) {
    // Get Request
    r->req_type = HTTP_GET;
  } else if (req->type == 2) {
    // Post Request
    r->req_type = HTTP_POST;
  } else if (req->type == 8) {
    // Put Request
    r->req_type = HTTP_PUT;
  } else if (req->type == 16) {
    // Delete Request
    r->req_type = HTTP_DELETE;
  } else {
    // Unknown Request type
    r->req_type = UNKNOWN;
  }

  std::string resp = "";
  CallbackInterface cb;

  // Call the callback, store the return value in a string sent in a response
  try {
    auto search = callback_map.find(uri);
    if (search != callback_map.end()) {
      cb = callback_map[uri];
      try {
        resp = (*cb)(r);
      }
      catch (std::exception& e) {
        err->err_code = HTTP_BADREQUEST;
        err->err_message = e.what();
      }
    } else {
      // Not found, call default callback
      cb = callback_map["default"];
      try {
        resp = (*cb)(r);
      }
      catch (std::exception& e) {
        err->err_code = HTTP_BADREQUEST;
        err->err_message = e.what();
      }
    }
  }
  catch (std::exception& e) {
    err->err_code = HTTP_NOTFOUND;
    err->err_message = e.what();
  }

  struct evbuffer *buf = evbuffer_new();
  if (buf != NULL) {
    evbuffer_add_printf(buf, resp.c_str(), uri_cstr);

    // Send a success response if no error is detected
    if (r->req_err->err_code == NOERROR) {
      evhttp_send_reply(req, HTTP_OK, "OK", buf);
    } else {
      // Send a failure response
      evhttp_send_reply(req, err->err_code, err->err_message.c_str(), buf);
    }
    evbuffer_free(buf);
  }

  delete r;
}
Exemplo n.º 3
0
void servlet(struct evhttp_request *req, struct evbuffer *evb, const char *get_query) {
    /*dbi_conn conn;
    dbi_result result;           
    unsigned int idnumber;
    char *fullname;
    
    dbi_initialize(NULL);
    conn = dbi_conn_new("mysql");    
    dbi_conn_set_option(conn, "host", "localhost");
    dbi_conn_set_option(conn, "username", "root");
    dbi_conn_set_option(conn, "password", "root");
    dbi_conn_set_option(conn, "dbname", "test");
    dbi_conn_set_option(conn, "encoding", "UTF-8");
    if (dbi_conn_connect(conn) < 0) {
      printf("Could not connect");
    } else {
        result = dbi_conn_queryf(conn, "SELECT id, name FROM test");
        
        if (result) {
            printf("dbi_result_get_numrows: %u", dbi_result_get_numrows(result));
            
            while (dbi_result_next_row(result)) {
                idnumber = dbi_result_get_uint(result, "id");
                fullname = dbi_result_get_string(result, "name");
                printf("%i. %s", idnumber, fullname);
            }
        
            dbi_result_free(result);
        }
        
        dbi_conn_close(conn);      
    }*/
    

    
    time_t now;
    time(&now);
    const char *value;
    struct evkeyvalq params;
    char *data;
    size_t len;


    if (evhttp_request_get_command(req) == EVHTTP_REQ_GET) {
        evhttp_parse_query_str(get_query, &params);
        value = evhttp_find_header(&params, "first_name");
    } else {
        len = evbuffer_get_length(evhttp_request_get_input_buffer(req));
        struct evbuffer *in_evb = evhttp_request_get_input_buffer(req);
        data = malloc(len + 1);
        evbuffer_copyout(in_evb, data, len);
        data[len] = '\0';
        evhttp_parse_query_str(data, &params);
        value = evhttp_find_header(&params, "first_name");
    }

    
    evbuffer_add_printf(evb, "<html>\n <head>\n"
	    "  <title>C servlet</title>\n"
	    " </head>\n"
	    " <body>\n"
	    "  <h1>C servlet</h1>\n"
	    " <p>Current time is: %s (GMT)</p>" 
	    " <p>First name is: %s</p>\n<hr>\n"
	    "<form action=\"/servlet\" method=\"POST\">\n"
	    "First name <input type=\"text\" name=\"first_name\">"
	    "<input type=\"submit\" value=\"send via post\">"
	    "</form>\n"
	    "<p>COOKIE: %s</p>"
	    "<p><a href=\"/servlet?first_name=John\">GET with parameters</a></p>"
	    "</body><html>", 
	    ctime(&now),
        value,
	    http_get_cookie(req, "CSESSID"));
    evhttp_add_header(evhttp_request_get_output_headers(req),
	    "Content-Type", "text/html");
	evhttp_add_header(evhttp_request_get_output_headers(req),
	    "Set-Cookie", "CSESSID=435J43L523J4TTYYY; Path=/; Domain=intranet2.local");
	evhttp_add_header(evhttp_request_get_output_headers(req),
	    "Set-Cookie", "[email protected]; Path=/; Domain=intranet2.local");
	evhttp_add_header(evhttp_request_get_output_headers(req),
	    "Server", "green httpd");
	evhttp_send_reply(req, 200, "OK", evb);
	
	if (evhttp_request_get_command(req) != EVHTTP_REQ_GET) {
	    evhttp_clear_headers(&params);
        free(data);
	}
}
Exemplo n.º 4
0
void cm_getblock(evhtp_request_t *req, void *arg) {
    enum {
        err_param = -1,
        err_db = -2,
        err_etc = -3,
        err_needlogin = -4,
    };
    
    evbuffer *evbuf = req->buffer_in;
    int sz = evbuffer_get_length(evbuf);
    char *inbuf = (char*)malloc(sz + 1);
    Autofree _af_buf(inbuf);
    evbuffer_copyout(evbuf, inbuf, sz);
    inbuf[sz] = 0;
    
    CommaReader commaReader(inbuf);
    float posX, posY;
    commaReader.readFloat(posX);
    commaReader.readFloat(posY);
    if (commaReader.getStatus()){
        return cm_send_error(err_param, req);
    }
    
    redisContext *redis = cm_get_context()->redis;
    if (redis->err) {
        return cm_send_error(err_db, req);
    }
    
    cm_session session;
    int err = cm_find_session(req, session);
    if (err == 0) {
        char buf[128];
        int n = snprintf(buf, sizeof(buf), "HMSET diguser:%s x %.1f y %.1f", session.userid.c_str(), posX, posY);
        if (n < 0) {
            return cm_send_error(err_etc, req);
        }
        redisReply *reply = (redisReply*)redisCommand(redis, buf);
        if (reply == NULL){
            return cm_send_error(err_db, req);
        }
        freeReplyObject(reply);
    } if (err == -2) { //err_expired
        return cm_send_error(err_needlogin, req);
    }
    
    std::stringstream ss;
    ss << "MGET";
    size_t nBlock = 0;
    std::vector<int> xys;
    while (1) {
        int x, y;
        commaReader.readInt(x);
        commaReader.readInt(y);
        int status = commaReader.getStatus();
        if (status < 0)
            break;
        if (x < 0 || x >= BLOCK_MAX || y < 0 || y >= BLOCK_MAX)
            break;
            
        xys.push_back(x);
        xys.push_back(y);
        ss << " block:" << x << "," << y;
        ++nBlock;
        if (status > 0)
            break;
    }
    if (nBlock==0) {
        return cm_send_error(err_param, req);
    }
    
    redisReply *reply = (redisReply*)redisCommand(redis, ss.str().c_str());
    if (reply == NULL){
        return cm_send_error(err_param, req);
    }
        
    std::stringstream out;
    out << "{\"error\":0, \"data\":{";
    char buf[CELLS_PER_BLOCK_SIDE*CELLS_PER_BLOCK_SIDE/8] = {0};
    if (reply->type == REDIS_REPLY_ARRAY && reply->elements == nBlock) {
        for (size_t i = 0; i < reply->elements; ++i) {
            redisReply *rp = reply->element[i];
            if (rp->str && rp->len <= (int)sizeof(buf)) {
                memset(buf, 0, sizeof(buf));
                memcpy(buf, rp->str, rp->len);
                char *b64 = base64_cf(buf, sizeof(buf));
                if (i > 0)
                    out << ",";
                out << "\"" << xys[i*2] << "," << xys[i*2+1] << "\":\"" << b64 << "\"";
                free(b64);
            } else {
                if (i > 0)
                    out << ",";
                out << "\"" << xys[i*2] << "," << xys[i*2+1] << "\":" << 0;
            }
        }
    } else {
        cm_send_error(err_db, req);
    }
    out << "}}";
    evbuffer_add_printf(req->buffer_out, "%s", out.str().c_str());
    evhtp_send_reply(req, EVHTP_RES_OK);
    freeReplyObject(reply);
}
Exemplo n.º 5
0
/* Функция обратного вызова для события: данные готовы для чтения в buf_ev */
static void echo_read_cb(struct bufferevent *buf_ev, void *arg) {
    struct evbuffer *buf_input = bufferevent_get_input(buf_ev);
    struct evbuffer *buf_output = bufferevent_get_output(buf_ev);

    size_t length = evbuffer_get_length(buf_input);

    char recvBuf[10000];

    evbuffer_copyout(buf_input, recvBuf, length);
    recvBuf[length] = '\0';

    std::istringstream split(recvBuf);
    std::string sRequestFileName;
    for (std::string token; std::getline(split, token);) {
        if (token.find("GET ") != std::string::npos) {
            std::istringstream ss(token);
            std::getline(ss, sRequestFileName, ' '); // GET
            std::getline(ss, sRequestFileName, ' '); // fname
        }
    }

    if (sRequestFileName.empty()) {
        std::cout << "invalid request" << std::endl;
        //onDisconnect();
        bufferevent_free(buf_ev);

        return;
    }

    std::cout << "GET " << sRequestFileName << std::endl;

    std::string sUsedFileName;
    if (sRequestFileName == "/")
        sUsedFileName = "/index.html";
    else {
        std::stringstream ss(sRequestFileName);
        std::getline(ss, sUsedFileName, '?');
        //sUsedFileName = sRequestFileName;
    }


    FILE *f = fopen((mainDir + sUsedFileName).c_str(), "r");

    if (f == NULL) { // 404
        std::cout << "No page " << (mainDir + sUsedFileName) << ", disconnecting." << std::endl;

        //std::string s404 = "HTTP/1.1 404 Not Found\r\n\r\n";
        std::string s404 = "HTTP/1.0 404 Not Found\r\nContent-Length: 0\r\nContent-Type: text/html\r\n\r\n";
/*			std::string s404 = "HTTP/1.1 ";
			s404 += sRequestFileName;
			const char sz404page[] = "<html><body>404 Page not found :(</html></body>";
			s404 += " 404 Not Found\r\nContent-Type: text/html;charset=win-1251\r\nContent-Length: ";
			s404 += std::to_string(sizeof(sz404page));
			s404 += "\r\nCache - Control: no - cache, no - store\r\n\r\n";
			s404 += sz404page;*/

        //send(m_sock, s404.c_str(), s404.length(), 0);
        bufferevent_write(buf_ev, s404.c_str(), s404.length());
        std::cout << s404 << std::endl;
        bufferevent_flush(buf_ev, EV_WRITE, BEV_NORMAL);

        //onDisconnect();

        //bufferevent_free(buf_ev);

        return;
    }

    long lSize = 0;
    if (fseek(f, 0, SEEK_END) == 0) {
        lSize = ftell(f);
        fseek(f, 0, SEEK_SET);
    }

    char *pBuf = new char[lSize + 1];

    if (fread(pBuf, lSize, 1, f) != 1) { // read error
        delete[] pBuf;

        std::cout << "Read error, disconnecting." << std::endl;

        std::string s404 = "HTTP/1.1 ";
        s404 += sRequestFileName;
        const char sz404page[] = "<html><body>404 Page not found :(</html></body>";
        s404 += " 404 Not Found\r\nContent-Type: text/html;charset=win-1251\r\nContent-Length: ";
        s404 += std::to_string(sizeof(sz404page));
        s404 += "\r\nCache - Control: no - cache, no - store\r\n\r\n";
        s404 += sz404page;

        //send(m_sock, s404.c_str(), s404.length(), 0);
        bufferevent_write(buf_ev, s404.c_str(), s404.length());

        //onDisconnect();
        //bufferevent_free(buf_ev);

        fclose(f);
        return;
    };

    std::string sMsg = "HTTP/1.1 ";
    sMsg += sRequestFileName;
    sMsg += " 200 OK \r\nContent-Type: text/html;charset=win-1251\r\nContent-Length: ";

    //if( pBuf[1] != 'h' )
    //	sMsg += std::to_string(lSize + 12 + 14 - 1);
    //else
    sMsg += std::to_string(lSize - 1);
    sMsg += "\r\nCache - Control: no - cache, no - store\r\n\r\n";


    pBuf[lSize] = '\0';

//		if( pBuf[1] != 'h' )
//			sMsg += "<html><body>";
    sMsg += pBuf;
    sMsg.pop_back();
    delete[] pBuf;
    //if( pBuf[1] != 'h' )
    //	sMsg += "</body></html>";

    if (bufferevent_write(buf_ev, sMsg.c_str(), sMsg.length()) != 0) {
        std::cout << "Send fails, disconnecting." << std::endl;

        //onDisconnect();
        //bufferevent_free(buf_ev);

        fclose(f);
        return;
    }

    std::cout << "File " << sUsedFileName << " transferred." << std::endl;
    fclose(f);
}
Exemplo n.º 6
0
struct evbuffer *
evbuffer_b2u(struct evbuffer *source)
{
    unsigned char c[16];
    int out = 0;

    if (evbuffer_get_length(source) == 0)
	return source;

    struct evbuffer *destination = evbuffer_new();

    // Peek at first byte
    while (evbuffer_copyout(source, c, 1) > 0) {
	if (isascii(c[0])) {
	    if (evbuffer_add(destination, c, 1) < 0)
		break;

	    // Remove byte from source buffer
	    evbuffer_drain(source, 1);
	    out++;
	} else {
	    // Big5
	    int todrain = 2;

	    // Handle in-character colors
	    int fg = -1, bg = -1, bright = -1;
	    int n = evbuffer_copyout(source, c, sizeof(c));
	    if (n < 2)
		break;
	    while (c[1] == '\033') {
		c[n - 1] = '\0';

		// At least have \033[m
		if (n < 4 || c[2] != '[')
		    break;

		unsigned char *p = c + 3;
		if (*p == 'm') {
		    // ANSI reset
		    fg = 7;
		    bg = 0;
		    bright = 0;
		}
		while (1) {
		    int v = (int) strtol((char *)p, (char **)&p, 10);
		    if (*p != 'm' && *p != ';')
			break;

		    if (v == 0)
			bright = 0;
		    else if (v == 1)
			bright = 1;
		    else if (v >= 30 && v <= 37)
			fg = v;
		    else if (v >= 40 && v <= 47)
			bg = v;

		    if (*p == 'm')
			break;
		    p++;
		}
		if (*p != 'm') {
		    // Skip malicious or unsupported codes
		    fg = bg = bright = -1;
		    break;
		} else {
		    evbuffer_drain(source, p - c + 1);
		    todrain = 1; // We keep a byte on buffer, so fix offset
		    n = evbuffer_copyout(source, c + 1, sizeof(c) - 1);
		    if (n < 1)
			break;
		    n++;
		}
	    }
#ifdef EXTENDED_INCHAR_ANSI
	    // Output control codes before the Big5 character
	    if (fg >= 0 || bg >= 0 || bright >= 0) {
                int dlen = evbuffer_add_ext_ansi_escape_code(destination, fg, bg, bright);
                if (dlen < 0)
                    break;
                out += dlen;
	    }
#endif

	    // n may be changed, check again
	    if (n < 2)
		break;

	    uint8_t utf8[4];
	    int len = ucs2utf(b2u_table[c[0] << 8 | c[1]], utf8);
	    utf8[len] = 0;

	    if (evbuffer_add(destination, utf8, len) < 0)
		break;

#ifndef EXTENDED_INCHAR_ANSI
            // Output in-char control codes to make state consistent
            if (fg >= 0 || bg >= 0 || bright >= 0) {
                int dlen = evbuffer_add_ansi_escape_code(destination, fg, bg, bright);
                if (dlen < 0)
                    break;
                out += dlen;
            }
#endif

	    // Remove DBCS character from source buffer
	    evbuffer_drain(source, todrain);
	    out += len;
	}
    }

    if (evbuffer_get_length(source) == 0 && out) {
	// Success
	evbuffer_free(source);
	return destination;
    }

    // Fail
    evbuffer_free(source);
    evbuffer_free(destination);
    return NULL;
}
Exemplo n.º 7
0
Arquivo: net.c Projeto: libbtc/libbtc
void read_cb(struct bufferevent* bev, void* ctx)
{
    struct evbuffer* input = bufferevent_get_input(bev);
    if (!input)
        return;

    size_t length = evbuffer_get_length(input);

    btc_node *node = (btc_node *)ctx;

    // expand the cstring buffer if required
    cstr_alloc_minsize(node->recvBuffer, node->recvBuffer->len+length);

    // copy direct to cstring, avoid another heap buffer
    evbuffer_copyout(input, node->recvBuffer->str+node->recvBuffer->len, length);
    node->recvBuffer->len += length;

    // drain the event buffer
    evbuffer_drain(input, length);

    struct const_buffer buf = {node->recvBuffer->str, node->recvBuffer->len};
    btc_p2p_msg_hdr hdr;
    char *read_upto = NULL;

    do {
        //check if message is complete
        if (buf.len < BTC_P2P_HDRSZ)
        {
            break;
        }

        btc_p2p_deser_msghdr(&hdr, &buf);
        if (buf.len < hdr.data_len)
        {
            //if we haven't read the whole message, continue and wait for the next chunk
            break;
        }
        if (buf.len >= hdr.data_len)
        {
            //at least one message is complete

            struct const_buffer cmd_data_buf = {buf.p, buf.len};
            btc_node_parse_message(node, &hdr, &cmd_data_buf);

            //skip the size of the whole message
            buf.p += hdr.data_len;
            buf.len -= hdr.data_len;

            read_upto = (void *)buf.p;
        }
        if (buf.len == 0)
        {
            //if we have "consumed" the whole buffer
            node->recvBuffer->len = 0;
            break;
        }
    } while(1);

    if (read_upto != NULL && node->recvBuffer->len != 0 && read_upto != (node->recvBuffer->str + node->recvBuffer->len))
    {
        char *end = node->recvBuffer->str + node->recvBuffer->len;
        size_t available_chunk_data = end - read_upto;
        //partial message
        cstring *tmp = cstr_new_buf(read_upto, available_chunk_data);
        cstr_free(node->recvBuffer, true);
        node->recvBuffer = tmp;
    }
}
HandleRequestReply WebHandler::parsePost(const RequestInfo& requestInfo,
					 RequestOutput& requestOutput,
					 StringMap& postValues) {
    std::string buff;

    if (requestInfo.requestBody == nullptr) RETURN_ERROR("no body in post request");

    const size_t bodyLen = evbuffer_get_length(requestInfo.requestBody);
    if (bodyLen >= MAX_POST_BODY_LEN || (int) bodyLen < 1) {
      std::string errMsg = "body len in post is bad (got:"; INT2STR(errMsg, bodyLen);
      errMsg << " max:"; INT2STR(errMsg, MAX_POST_BODY_LEN); errMsg << ")";
      RETURN_ERROR(errMsg);
    }

    char data[bodyLen + 1];
    evbuffer_copyout(requestInfo.requestBody, data, bodyLen);
 
#if 0
    // DEBUG!!!
    data[bodyLen] = 0;
    printf("%s: %s\n", requestInfo.uriPath, data);
#endif
    
    bool gettingValuePortion = false;  // state of what is being assembled (key vs value)
    char tmpBuffer[bodyLen + 1];
    int tmpBufferOffset = 0;
    const char* const currKey = tmpBuffer;
    const char* currValue = "";

    memset(tmpBuffer, 0, bodyLen + 1);

    for (int i=0; i < (int) bodyLen; ++i) {
      char ch = data[i];

      // translate plus into space
      if (ch == '+') ch = ' ';

      // check for name delimiter
      if (ch == '=') {
	tmpBuffer[tmpBufferOffset] = 0;  // terminate key c str (key)
	++tmpBufferOffset;
	currValue = &tmpBuffer[tmpBufferOffset];
	tmpBuffer[tmpBufferOffset] = 0;  // terminate key c str (value)
	gettingValuePortion = true;
	continue;
      }

      // check for value delimiter
      if (ch == '&') {
	if (gettingValuePortion && *currKey != 0) {
	  tmpBuffer[tmpBufferOffset] = 0;  // terminate value c str
	  postValues[ currKey ] = currValue;  // add key/value to map
	}
	currValue = "";
	tmpBufferOffset = 0;  // reset usage of tmpBuffer
	tmpBuffer[tmpBufferOffset] = 0;  // terminate value c str
	gettingValuePortion = false;
	continue;
      }
      
      // convert encoded value to character
      if (ch == '%') {
	// protect against buffer being too small to hold 2 extra characters
	if (i >= (int) (bodyLen - 2)) {
	  tmpBuffer[tmpBufferOffset] = 0;  // terminate key c str
	  break;
	}
	const char hex[] = { data[i+1], data[i+2], 0 };
	ch = strtoul(hex, NULL, 16);
	i += 2;
      }

      tmpBuffer[tmpBufferOffset] = ch;
      tmpBufferOffset++;
    }

    // add final value from body of post
    if (gettingValuePortion && *currKey != 0) {
      tmpBuffer[tmpBufferOffset] = 0;  // terminate value c str
      postValues[ currKey ] = currValue;
    }
    
    return replyOk;
}
Exemplo n.º 9
0
bool __send_export_info(struct bufferevent* bev, struct nbd_handle* handle)
{
    struct nbd_new_handshake_finish hdr = {
                                            .size = htobe64(handle->size),
                                            .export_flags =
                                                htobe16(NBD_FLAG_HAS_FLAGS |
                                                        NBD_FLAG_SEND_FLUSH |
                                                        NBD_FLAG_SEND_FUA |
                                                        NBD_FLAG_ROTATIONAL |
                                                        NBD_FLAG_SEND_TRIM),
                                            .pad = {0}
                                          };
    bufferevent_write(bev, &hdr, sizeof(hdr));
    return true;
}

bool __send_unsupported_opt(struct evbuffer* out, uint32_t option)
{
    struct nbd_res_opt_header hdr = {
                                        .magic =
                                            htobe64(GAMMARAY_NBD_REPLY_MAGIC), 
                                        .option = option,
                                        .type = htobe32(NBD_REP_ERR_UNSUP),
                                        .len = 0
                                    };
    evbuffer_add(out, &hdr, sizeof(hdr));
    return true;
}

bool __send_response(struct bufferevent* bev, uint32_t error,
                     uint64_t handle, uint8_t* data, uint32_t len)
{
    struct nbd_res_header hdr = {
                                    .magic  = htobe32(GAMMARAY_NBD_REP_MAGIC),
                                    .error  = htobe32(error),
                                    .handle = htobe64(handle) 
                                };

    bufferevent_write(bev, &hdr, sizeof(hdr));
    if (data && len)
        bufferevent_write(bev, data, (size_t) len);

    return true;
}

bool __check_opt_header(struct bufferevent* bev, struct evbuffer* in,
                        struct evbuffer* out, struct nbd_client* client)
{
    struct nbd_opt_header* peek;
    char* export_name;
    uint32_t name_len;
    peek = (struct nbd_opt_header*)
           evbuffer_pullup(in, sizeof(struct nbd_opt_header));

    if (peek)
    {
        if (be64toh(peek->magic) == GAMMARAY_NBD_NEW_PROTOCOL)
        {
            switch (be32toh(peek->option))
            {
                case NBD_OPT_EXPORT_NAME:
                    name_len = be32toh(peek->len);

                    if (name_len != client->handle->name_len)
                        goto fail;

                    if (evbuffer_get_length(in) <
                        sizeof(struct nbd_opt_header) + name_len)
                        return true;

                    evbuffer_drain(in, sizeof(struct nbd_opt_header));
                    export_name = (char*) evbuffer_pullup(in, name_len);

                    if (export_name == NULL)
                    {
                        client->state = NBD_DISCONNECTED;
                        return false;
                    }

                    if (strncmp(export_name,
                                client->handle->export_name,
                                name_len) == 0)
                    {
                        __send_export_info(bev, client->handle);
                        client->state = NBD_DATA_PUSHING;
                        evbuffer_drain(in, name_len);
                        return false;
                    }
                    else
                    {
                        client->state = NBD_DISCONNECTED;
                        return false;
                    }

                case NBD_OPT_ABORT:
                    goto fail;

                case NBD_OPT_LIST:
                default:
                    __send_unsupported_opt(out, peek->option);
                    return false;
            };
        }
fail:
        client->state = NBD_DISCONNECTED;
        return false;
    }

    return true;
}

uint32_t __handle_read(struct nbd_req_header* req, struct nbd_client* client)
{
    off64_t offset;
    uint8_t* buf;
    ssize_t ret;
    size_t len;
    int fd;

    offset = be64toh(req->offset);
    len = be32toh(req->length);
    buf = realloc(client->buf, len);
    client->buf = buf;
    fd = client->handle->fd;

    assert(buf != NULL);

    if (lseek64(fd, offset, SEEK_SET) == (off64_t) -1)
        return errno;

    while (len)
    {
        if ((ret = read(fd, buf, len)) == (ssize_t) -1)
            return errno;
        len -= ret;
    }

    return 0;
}

uint32_t __handle_write(struct nbd_req_header* req, struct nbd_client* client,
                        struct evbuffer* in)
{
    off64_t offset;
    uint8_t* buf;
    ssize_t ret;
    size_t len, pos = 0;
    int fd;
    struct redisAsyncContext* redis_c;
    struct timeval curtime;

    offset = be64toh(req->offset);
    len = be32toh(req->length);
    buf = realloc(client->buf, len);
    client->buf = buf;
    fd = client->handle->fd;
    redis_c = client->handle->redis_c;

    assert(in != NULL);
    assert(buf != NULL);

    if (evbuffer_get_length(in) < sizeof(struct nbd_req_header) + len)
        return -1;

    evbuffer_drain(in, sizeof(struct nbd_req_header));

    if (evbuffer_copyout(in, buf, len) < len)
        return -1;

    client->write_count += 1;
    client->write_bytes += len;
    gettimeofday(&curtime, NULL);
    fprintf(stderr, "\t[%ld] write size: %zd\n", curtime.tv_sec * 1000000 +
                                                 curtime.tv_usec, len);

    if (fd < 0)
    {
        assert(redis_c != NULL);
        offset /= 512;
        assert(redisAsyncCommand(redis_c, &redis_async_callback, NULL,
                                 "LPUSH writequeue %b", &offset,
                                 sizeof(offset)) == REDIS_OK);
        assert(redisAsyncCommand(redis_c, &redis_async_callback, NULL,
                                 "LPUSH writequeue %b", buf, len) == REDIS_OK);
        return 0;
    }

    if (lseek64(fd, offset, SEEK_SET) == (off64_t) -1)
        return errno;

    while (pos < len)
    {
        if ((ret = write(fd, &(buf[pos]), len)) == (ssize_t) -1)
            return errno;
        pos += ret;
    }

    return 0;
}
Exemplo n.º 10
0
/* Callback used for the /dump URI, and for every non-GET request:
 * dumps all information to stdout and gives back a trivial 200 ok */
static void
s2info_request_cb(struct evhttp_request *req, void *arg)
{

  struct evkeyvalq    args;
  struct evbuffer *inputBuffer = evhttp_request_get_input_buffer (req);
  size_t record_len = evbuffer_get_length(inputBuffer);
  char *postData = NULL;
  const char *path = "/?";
  if (record_len > 0) { 
    postData = (char *)malloc(strlen(path) + record_len + 10);
    postData[0] = '/';
    postData[1] = '?';
    evbuffer_pullup(inputBuffer, -1);                                                                                                                                                     
    evbuffer_copyout(inputBuffer, (char *)postData + strlen(path), record_len);
    postData[strlen(path) + record_len] = '\0';
    printf("trying to parse: %s\n", (const char *)postData);
    evhttp_parse_query((const char *)postData, &args);
  } else {
    const char *uri = evhttp_request_get_uri(req);
    evhttp_parse_query(uri, &args);
  }

  char* callback = (char *)evhttp_find_header(&args, "callback");



  char* ids = (char *)evhttp_find_header(&args, "id");
  std::vector<S2CellId> cellids_vector;
 
  if (ids != NULL) {
    printf("%s\n", ids);
    std::vector<std::string> ids_vector = split(string(ids), ',');
    bool treat_as_tokens = false;
    int num_evenly_divisible = 0;
    for (int i = 0; i < ids_vector.size(); i++) {
      const char *str = ids_vector[i].c_str();
      errno = 0;    /* To distinguish success/failure after call */
      char *endptr;
      uint64_t id = strtoull(str, &endptr, 10);

      if (strlen(endptr) != 0) {
        printf("failed to parse as long long, treating everything as tokens\n");
        treat_as_tokens = true;
      }
      else if (id % 1000 == 0) {
        printf("was even divisible by 1000, assume this was a misinterpreted token\n");
        num_evenly_divisible += 1;
      }
    }

    if (num_evenly_divisible == ids_vector.size()) {
      treat_as_tokens = true;
    }
   
    for (int i = 0; i < ids_vector.size(); i++) {
      const char *str = ids_vector[i].c_str();
      errno = 0;    /* To distinguish success/failure after call */
      char *endptr;
      uint64_t id = strtoull(str, &endptr, 10);
      /*if (str[0] != '-') {
        id = strtoul(str, &endptr, 10);
      }*/

      printf("endptr %d\n", strlen(endptr));
      printf("str %s\n", str);
      printf("id %lld\n", id);

      if (strlen(endptr) != 0 || treat_as_tokens) {
        printf("failed to parse as long long\n");
        cellids_vector.push_back(S2CellId(S2CellId::FromToken(str).id()));
      } else {
        printf("%lld\n", id);
        printf("id != 0 ? %d -- %s %d\n", (id != 0), str, strlen(str));
        printf("is_valid? %d\n", S2CellId(id).is_valid());
        cellids_vector.push_back(S2CellId(id));
      } 
    }
  }

	evhttp_add_header(evhttp_request_get_output_headers(req),
		    "Content-Type", "application/json");
	struct evbuffer *evb = NULL;
	evb = evbuffer_new();
  char* json = s2CellIdsToJson(callback, cellids_vector);
  evbuffer_add_printf(evb, "%s", json);
	evhttp_send_reply(req, 200, "OK", evb);
 
  free(json);

  if (evb)
    evbuffer_free(evb);
}
Exemplo n.º 11
0
static void
s2cover_request_cb(struct evhttp_request *req, void *arg)
{
  struct evkeyvalq  args;

  struct evbuffer *inputBuffer = evhttp_request_get_input_buffer (req);
  size_t record_len = evbuffer_get_length(inputBuffer);
  char *postData = NULL;
  const char *path = "/?";
  if (record_len > 0) { 
    postData = (char *)malloc(strlen(path) + record_len + 10);
    postData[0] = '/';
    postData[1] = '?';
    evbuffer_pullup(inputBuffer, -1);                                                                                                                                                     
    evbuffer_copyout(inputBuffer, (char *)postData + strlen(path), record_len);
    postData[strlen(path) + record_len] = '\0';
    printf("trying to parse: %s\n", (const char *)postData);
    evhttp_parse_query((const char *)postData, &args);
    char* points = (char *)evhttp_find_header(&args, "points");
    cout << points << endl;
  } else {
    const char *uri = evhttp_request_get_uri(req);
    evhttp_parse_query(uri, &args);
  }

  char* callback = (char *)evhttp_find_header(&args, "callback");

  char* points = (char *)evhttp_find_header(&args, "points");
  std::vector<S2CellId> cellids_vector;
  if (points != NULL) {
    printf(points);
    scoped_ptr<S2PolygonBuilder> builder(new S2PolygonBuilder(S2PolygonBuilderOptions::DIRECTED_XOR()));
    
    std::vector<std::string> points_vector = split(string(points), ',');
    std::vector<S2Point> s2points_vector;

    for (int i = 0; i < points_vector.size(); i += 2) {
      char *endptr;
      s2points_vector.push_back(S2LatLng::FromDegrees(
        strtod(points_vector[i].c_str(), &endptr),
        strtod(points_vector[i+1].c_str(), &endptr)
      ).ToPoint());
    }

    if (s2points_vector.size() == 1) {
      char* min_level = (char *)evhttp_find_header(&args, "min_level");
      if (min_level == NULL) {
        min_level = (char *)evhttp_find_header(&args, "max_level");
      }
      if (min_level == NULL) {
        min_level = "14";
      }

      int min_level_int = atoi(min_level);
      if (min_level_int > S2::kMaxCellLevel) {
        min_level_int = S2::kMaxCellLevel;
      }
      if (min_level_int < 0) {
        min_level_int = 0;
      }

      cellids_vector.push_back(S2CellId::FromPoint(s2points_vector[0]).parent(min_level_int));
    } else {
      for (int i = 0; i < s2points_vector.size(); i++) {
        builder->AddEdge(
          s2points_vector[i],
          s2points_vector[(i + 1) % s2points_vector.size()]);
      }

      S2Polygon polygon;
      typedef vector<pair<S2Point, S2Point> > EdgeList;
      EdgeList edgeList;
      builder->AssemblePolygon(&polygon, &edgeList);

      S2RegionCoverer coverer;

      char* min_level = (char *)evhttp_find_header(&args, "min_level");
      if (min_level) {
	int min_level_int = atoi(min_level);
	if (min_level_int > S2::kMaxCellLevel) {
	  min_level_int = S2::kMaxCellLevel;
        }
        if (min_level_int < 0) {
          min_level_int = 0;
        }
        coverer.set_min_level(min_level_int);
      }

      char* max_level = (char *)evhttp_find_header(&args, "max_level");
      if (max_level) {
	int max_level_int = atoi(max_level);
	if (max_level_int > S2::kMaxCellLevel) {
	  max_level_int = S2::kMaxCellLevel;
        }
        if (max_level_int < 0) {
          max_level_int = 0;
        }
        coverer.set_max_level(max_level_int);
      }

      char* level_mod = (char *)evhttp_find_header(&args, "level_mod");
      if (level_mod) {
        coverer.set_level_mod(atoi(level_mod));
      }

      char* max_cells = (char *)evhttp_find_header(&args, "max_cells");
      if (max_cells) {
        coverer.set_max_cells(atoi(max_cells));
      }

      coverer.GetCovering(polygon, &cellids_vector); 
    }
  }

  printf("\n");

	evhttp_add_header(evhttp_request_get_output_headers(req),
		    "Content-Type", "application/json");
	struct evbuffer *evb = NULL;
	evb = evbuffer_new();
  char* json = s2CellIdsToJson(callback, cellids_vector);
  evbuffer_add_printf(evb, "%s", json);
	evhttp_send_reply(req, 200, "OK", evb);
 
  free(json);

  if (postData)
    free(postData);

  if (evb)
    evbuffer_free(evb);
}
Exemplo n.º 12
0
void MessageManager::MessageDispatcher(struct bufferevent *bev, void *ctx)
{

	bufferevent_lock(bev);

	struct evbuffer *input = bufferevent_get_input(bev);
	evutil_socket_t socketFD = bufferevent_getfd(bev);

	uint32_t length = 0, evbufferLength;

	bool keepGoing = true;
	while(keepGoing)
	{
		evbufferLength = evbuffer_get_length(input);
		//If we don't even have enough data to read the length, just quit
		if(evbufferLength < sizeof(length))
		{
			keepGoing = false;
			continue;
		}

		//Copy the length field out of the message
		//	We only want to copy this data at first, because if the whole message hasn't reached us,
		//	we'll want the whole buffer still present here, undrained
		if(evbuffer_copyout(input, &length, sizeof(length)) != sizeof(length))
		{
			keepGoing = false;
			continue;
		}

		// Make sure the length appears valid
		// TODO: Assign some arbitrary max message size to avoid filling up memory by accident
		if(length < MESSAGE_MIN_SIZE)
		{
			LOG(WARNING, "Error parsing message: message too small.", "");
			evbuffer_drain(input, sizeof(length));
			keepGoing = false;
			continue;
		}

		//If we don't yet have enough data, then just quit and wait for more
		if(evbufferLength < length)
		{
			keepGoing = false;
			continue;
		}

		evbuffer_drain(input, sizeof(length));

		//Remove the length of the "length" variable itself
		length -= sizeof(length);
		char *buffer = (char*)malloc(length);

		if(buffer == NULL)
		{
			// This should never happen. If it does, probably because length is an absurd value (or we're out of memory)
			LOG(WARNING, "Error parsing message: malloc returned NULL. Out of memory?.", "");
			free(buffer);
			keepGoing = false;
			continue;
		}

		// Read in the actual message
		int bytesRead = evbuffer_remove(input, buffer, length);
		if(bytesRead == -1)
		{
			LOG(WARNING, "Error parsing message: couldn't remove data from buffer.", "");
		}
		else if((uint32_t)bytesRead != length)
		{
			LOG(WARNING, "Error parsing message: incorrect amount of data received than what expected.", "");
		}

		MessageEndpointLock endpoint = MessageManager::Instance().GetEndpoint(socketFD);
		if(endpoint.m_endpoint != NULL)
		{
			Message *message = Message::Deserialize(buffer, length);
			if(!endpoint.m_endpoint->PushMessage(message))
			{
				LOG(DEBUG, "Discarding message. Error in pushing it to a queue.", "");
			}
		}
		else
		{
			LOG(DEBUG, "Discarding message. Received it for a non-existent endpoint.", "");
		}

		free(buffer);
	}

	bufferevent_unlock(bev);
}