コード例 #1
0
ファイル: sock.cpp プロジェクト: littletiny/corotouine
// error event socket ( all client socket)
// connecting socket (client side client)
static void sock_buffer_error_event(bufferevent *bev, short what, void *arg)
{
    coro_sock *sock = (coro_sock *)arg;
    coro_event ev;
    ev.sock = bufferevent_getfd(bev);
    ev.sock = sock->sock;
    if ( what & BEV_EVENT_ERROR ) {
        SET_ERROR(sock->status);
        ev.event = SOCK_ERROR_NOTIFY;
    }
    else if ( what & BEV_EVENT_EOF ) {
        ev.event = SOCK_EOF_NOTIFY;
        SET_EOF(sock->status);
        if ( evbuffer_get_length(bufferevent_get_input(sock->bev)) ) {
            SET_READ(sock->status);
            // printf("set read: %d\n", ev.sock);
        }
    }
    else {
        ; // pass
    }
    sock->ctx->curev.push(ev);
    coro_yield_uthread(__g_coroutine_ctx->io, 0);
}
コード例 #2
0
ファイル: bufferevent_openssl.c プロジェクト: trasz/cbang
/* Called to extract data from the BIO. */
static int
bio_bufferevent_read(BIO *b, char *out, int outlen)
{
	int r = 0;
	struct evbuffer *input;

	BIO_clear_retry_flags(b);

	if (!out)
		return 0;
	if (!b->ptr)
		return -1;

	input = bufferevent_get_input(b->ptr);
	if (evbuffer_get_length(input) == 0) {
		/* If there's no data to read, say so. */
		BIO_set_retry_read(b);
		return -1;
	} else {
		r = evbuffer_remove(input, out, outlen);
	}

	return r;
}
コード例 #3
0
static void http_request_done(struct evhttp_request *req, void *ctx)
{
    HTTPReply *reply = static_cast<HTTPReply*>(ctx);

    if (req == nullptr) {
        /* If req is nullptr, it means an error occurred while connecting: the
         * error code will have been passed to http_error_cb.
         */
        reply->status = 0;
        return;
    }

    reply->status = evhttp_request_get_response_code(req);

    struct evbuffer *buf = evhttp_request_get_input_buffer(req);
    if (buf)
    {
        size_t size = evbuffer_get_length(buf);
        const char *data = (const char*)evbuffer_pullup(buf, size);
        if (data)
            reply->body = std::string(data, size);
        evbuffer_drain(buf, size);
    }
}
コード例 #4
0
ファイル: DScriptConsole.c プロジェクト: imasahiro/konoha3
static void userInput2Buff(struct evhttp_request *req, void *args)
{
	UserInput *ui = (UserInput *)args;
	struct event_base *base = ui->base;
	char *buff = ui->buff;
	struct evbuffer *body = evhttp_request_get_input_buffer(req);
	size_t len = evbuffer_get_length(body);
	unsigned char *requestLine;
	struct evbuffer *buf = evbuffer_new();

	switch(req->type) {
		case EVHTTP_REQ_POST:
			requestLine = evbuffer_pullup(body, -1);
			requestLine[len] = '\0';
			memcpy(buff, requestLine, len);
			evhttp_send_reply(req, HTTP_OK, "OK", buf);
			break;
		default:
			evhttp_send_error(req, HTTP_BADREQUEST, "Available POST only");
			break;
	}
	evbuffer_free(buf);
	event_base_loopbreak(base);
}
コード例 #5
0
ファイル: conn.c プロジェクト: ioerror/shim
static void
conn_readcb(struct bufferevent *bev, void *arg)
{
	struct conninfo *info = arg;
	struct evbuffer *inbuf = bufferevent_get_input(bev);
	unsigned char *data;
	unsigned char code;

	/* socks4 and socks4a both have an 8 byte response */
	if (evbuffer_get_length(inbuf) < 8) {
		log_debug("conn: waiting for full socks response");
		return;
	}

	data = evbuffer_pullup(inbuf, 8);
	code = data[1];
	evbuffer_drain(inbuf, 8);

	if (code != 0x5a) {
		finish_connection(info, 0, socks4_error_to_string(code));
	} else {
		finish_connection(info, 1, NULL);
	}
}
コード例 #6
0
ファイル: evhtp_s.cpp プロジェクト: austgl/libhttp
static void
_evhtp_connection_writecb(evbev_t * bev, void * arg) {
    evhtp_connection_t * c = reinterpret_cast<evhtp_connection_t*>(arg);

    if (c->request == NULL) {
        return;
    }

    if (c->request->finished == 0 || evbuffer_get_length(bufferevent_get_output(bev))) {
        return;
    }

    if (c->request->keepalive) {
        delete(c->request);
        c->request = NULL;
		c->parser->init(htp_type_request);
		c->parser->set_userdata(c);
    } else {
         delete c;
		 return ;
    }

    return;
}
コード例 #7
0
//********************************************************************************
// Event handler when there is data to be read
// General message format:
//   command:payload$
// New group:
//  -command = new
//  -payload = <empty>
// Store group info:
//  -command = new
//  -payload = <groupdata>
// Restore group info:
//  -command = restore
//  -payload = <empty>
// Remove group:
//  -command = remove
//  -payload = <empty>
//********************************************************************************
static void read_cb(struct bufferevent *bev, void *ctx)
{
    // Get input buffer
    struct evbuffer *input = bufferevent_get_input(bev);
    ev_uint32_t record_len = evbuffer_get_length(input);

    // Setup buffer to get data
    char* record = (char*) malloc(record_len);
    if (record == NULL)
        return;

    // Obtain data
    evbuffer_remove(input, record, record_len);

    // Store in structure
    //printf("Received: %s.\n", record);
    if(strncmp(record, "new", strlen("new")) == 0)
    {
        // First remove previous one, if there was one; then create a new one
        if(removeGroupSession())
        {
            printf("Removed old session\n");
        }

        printf("Starting new session\n");
        newGroupSession();

        printStaticPointer();
    }
    else if(strncmp(record, "store", strlen("store")) == 0)
    {
        // Check start data marker
        char* start = strchr(record, ':') + 1;
        char* endMarker = strrchr(record, '$');
        int msgLength = endMarker - start + 1; // Include marker in saved data

        // Turn into string
        char* dataToStore = (char*) malloc(msgLength + 1);  // +1 for null terminator
        memset(dataToStore, 0, msgLength + 1);
        memcpy(dataToStore, start, msgLength);

        // Store data in RVM
        printf("Received: %s \n", dataToStore);
        if(!updateGroupSession(dataToStore, strlen(dataToStore)+1))
            printf("Couldn't update group session as there was no session loaded\n");
        else
            printf("Stored: %s \n", g_groupState);

        free(dataToStore);
    }
    else if(strncmp(record, "restore", strlen("restore")) == 0)
    {
        // Restore command received; send information back
        printf("Restore\n");
        struct evbuffer *output = bufferevent_get_output(bev);

        if(g_groupState != NULL)
        {
            // Send msg
            printf("Sending %s.\n", g_groupState);
            evbuffer_add(output, g_groupState, strlen(g_groupState)+1);
        }
        else
        {
            evbuffer_add(output, "groupNotFound$", strlen("groupNotFound$")+1);
            printf("Couldn't restore group session as there was no session loaded\n");
        }
    }
    else if(strncmp(record, "remove", strlen("new")) == 0)
    {
        printf("Removing session\n");
        if(!removeGroupSession())
            printf("Couldn't remove group session as there was no session loaded\n");

        printStaticPointer();
    }
    else
    {
        printf("Invalid command received\n");
    }
}
コード例 #8
0
static void
add_response (struct evhttp_request * req,
              struct tr_rpc_server  * server,
              struct evbuffer       * out,
              struct evbuffer       * content)
{
  const char * key = "Accept-Encoding";
  const char * encoding = evhttp_find_header (req->input_headers, key);
  const int do_compress = encoding && strstr (encoding, "gzip");

  if (!do_compress)
    {
      evbuffer_add_buffer (out, content);
    }
  else
    {
      int state;
      struct evbuffer_iovec iovec[1];
      void * content_ptr = evbuffer_pullup (content, -1);
      const size_t content_len = evbuffer_get_length (content);

      if (!server->isStreamInitialized)
        {
          int compressionLevel;

          server->isStreamInitialized = true;
          server->stream.zalloc = (alloc_func) Z_NULL;
          server->stream.zfree = (free_func) Z_NULL;
          server->stream.opaque = (voidpf) Z_NULL;

          /* zlib's manual says: "Add 16 to windowBits to write a simple gzip header
           * and trailer around the compressed data instead of a zlib wrapper." */
#ifdef TR_LIGHTWEIGHT
          compressionLevel = Z_DEFAULT_COMPRESSION;
#else
          compressionLevel = Z_BEST_COMPRESSION;
#endif
          deflateInit2 (&server->stream, compressionLevel, Z_DEFLATED, 15+16, 8, Z_DEFAULT_STRATEGY);
        }

      server->stream.next_in = content_ptr;
      server->stream.avail_in = content_len;

      /* allocate space for the raw data and call deflate () just once --
       * we won't use the deflated data if it's longer than the raw data,
       * so it's okay to let deflate () run out of output buffer space */
      evbuffer_reserve_space (out, content_len, iovec, 1);
      server->stream.next_out = iovec[0].iov_base;
      server->stream.avail_out = iovec[0].iov_len;
      state = deflate (&server->stream, Z_FINISH);

      if (state == Z_STREAM_END)
        {
          iovec[0].iov_len -= server->stream.avail_out;

#if 0
          fprintf (stderr, "compressed response is %.2f of original (raw==%zu bytes; compressed==%zu)\n",
                   (double)evbuffer_get_length (out)/content_len,
                   content_len, evbuffer_get_length (out));
#endif
          evhttp_add_header (req->output_headers,
                             "Content-Encoding", "gzip");
        }
      else
        {
          memcpy (iovec[0].iov_base, content_ptr, content_len);
          iovec[0].iov_len = content_len;
        }

      evbuffer_commit_space (out, iovec, 1);
      deflateReset (&server->stream);
    }
}
コード例 #9
0
ファイル: forge-socket.c プロジェクト: 0x-Jin/toolforspider
// Grab these bytes, and close the connection.
// Even if we don't need to read any bytes,
// we have to have this so that libevent thinks we have
// a read event, so that it can timeout TCP connects
// (as a read timeout)
void read_cb(struct bufferevent *bev, void *arg)
{
	struct evbuffer *in = bufferevent_get_input(bev);
	struct state *st = arg;
	size_t len = evbuffer_get_length(in);
	struct in_addr addr;
	addr.s_addr = st->src_ip;

	log_debug("forge-socket", "read_cb for %s", inet_ntoa(addr));

	if (len > MAX_BANNER_LEN) {
		len = MAX_BANNER_LEN;
	}

	if (len > 0) {
		// Grab the banner	
		unsigned int i;
		unsigned char *buf = malloc(len+1);

		st->state = RECEIVED;

		if (!buf) {
			log_fatal("forge-socket", "cannot alloc %d byte buf", len+1);
			return;
		}
		evbuffer_remove(in, buf, len);
		
		printf("%s ", inet_ntoa(addr));

		if (st->conf->format == FORMAT_ASCII) {
			// Ascii
			buf[len] = '\0';
			printf("%s\n", buf);
		} else if (st->conf->format == FORMAT_HEX) {
			// Hex output
			for (i=0; i<len; i++) {
				printf("%02x", buf[i]);
			}
			printf("\n");
		} else if (st->conf->format == FORMAT_BASE64) {
			// Base64
			int i=0;
			char out[4] = {0,0,0,0};
			while (i < len) {
				uint32_t value = 0;
				value += (i < len) ? buf[i++] << 16 : 0; 	
				value += (i < len) ? buf[i++] <<  8 : 0;
				value += (i < len) ? buf[i++]       : 0;
				out[0] = BASE64_ALPHABET[(value >> 18) & 0x3F];
				out[1] = BASE64_ALPHABET[(value >> 12) & 0x3F];                                                                           
				out[2] = BASE64_ALPHABET[(value >>  6) & 0x3F];
				out[3] = BASE64_ALPHABET[(value      ) & 0x3F];
				if (i < len) {
					printf("%c%c%c%c", out[0], out[1], out[2], out[3]);
				}
			}
			if (len > 0) {
				switch (len % 3) {
				case 1:
					out[2] = '=';
				case 2:
					out[3] = '=';
				default:
					break;
				}
				printf("%c%c%c%c\n", out[0], out[1], out[2], out[3]);
			}
		}
コード例 #10
0
ファイル: bufferevent_sock.c プロジェクト: NeilHappy/libevent
static void
bufferevent_readcb(evutil_socket_t fd, short event, void *arg)
{
	struct bufferevent *bufev = arg;
	struct bufferevent_private *bufev_p =
	    EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
	struct evbuffer *input;
	int res = 0;
	short what = BEV_EVENT_READING;
	ev_ssize_t howmuch = -1, readmax=-1;

	bufferevent_incref_and_lock_(bufev);

	if (event == EV_TIMEOUT) {
		/* Note that we only check for event==EV_TIMEOUT. If
		 * event==EV_TIMEOUT|EV_READ, we can safely ignore the
		 * timeout, since a read has occurred */
		what |= BEV_EVENT_TIMEOUT;
		goto error;
	}

	input = bufev->input;

	/*
	 * If we have a high watermark configured then we don't want to
	 * read more data than would make us reach the watermark.
	 */
	if (bufev->wm_read.high != 0) {
		howmuch = bufev->wm_read.high - evbuffer_get_length(input);
		/* we somehow lowered the watermark, stop reading */
		if (howmuch <= 0) {
			bufferevent_wm_suspend_read(bufev);
			goto done;
		}
	}
	readmax = bufferevent_get_read_max_(bufev_p);
	if (howmuch < 0 || howmuch > readmax) /* The use of -1 for "unlimited"
					       * uglifies this code. XXXX */
		howmuch = readmax;
	if (bufev_p->read_suspended)
		goto done;

	evbuffer_unfreeze(input, 0);
	res = evbuffer_read(input, fd, (int)howmuch); /* XXXX evbuffer_read would do better to take and return ev_ssize_t */
	evbuffer_freeze(input, 0);

	if (res == -1) {
		int err = evutil_socket_geterror(fd);
		if (EVUTIL_ERR_RW_RETRIABLE(err))
			goto reschedule;
		/* error case */
		what |= BEV_EVENT_ERROR;
	} else if (res == 0) {
		/* eof case */
		what |= BEV_EVENT_EOF;
	}

	if (res <= 0)
		goto error;

	bufferevent_decrement_read_buckets_(bufev_p, res);

	/* Invoke the user callback - must always be called last */
	if (evbuffer_get_length(input) >= bufev->wm_read.low)
		bufferevent_run_readcb_(bufev);

	goto done;

 reschedule:
	goto done;

 error:
	bufferevent_disable(bufev, EV_READ);
	bufferevent_run_eventcb_(bufev, what);

 done:
	bufferevent_decref_and_unlock_(bufev);
}
コード例 #11
0
ファイル: libws_private.c プロジェクト: JoakimSoderberg/libws
void _ws_read_websocket(ws_t ws, struct evbuffer *in)
{
	assert(ws);
	assert(ws->bev);
	assert(in);

	LIBWS_LOG(LIBWS_DEBUG2, "Read websocket data");

	while (evbuffer_get_length(in))
	{
		// First read the websocket header.
		if (!ws->has_header)
		{
			size_t header_len;
			ev_ssize_t bytes_read;
			char header_buf[WS_HDR_MAX_SIZE];
			ws_parse_state_t state;

			LIBWS_LOG(LIBWS_DEBUG2, "Read websocket header");

			bytes_read = evbuffer_copyout(in, (void *)header_buf, 
											sizeof(header_buf));

			LIBWS_LOG(LIBWS_DEBUG2, "Copied %d header bytes", bytes_read);

			state = ws_unpack_header(&ws->header, &header_len, 
					(unsigned char *)header_buf, bytes_read);

			assert(state != WS_PARSE_STATE_USER_ABORT);

			// Look for protocol violations in the header.
			if (state != WS_PARSE_STATE_NEED_MORE && _ws_validate_header(ws))
			{
				state = WS_PARSE_STATE_ERROR;
			}

			switch (state)
			{
				case WS_PARSE_STATE_SUCCESS: 
				{
					ws_header_t *h = &ws->header;
					ws->has_header = 1;

					LIBWS_LOG(LIBWS_DEBUG2, "Got header (%lu bytes):\n"
						"fin = %d, rsv = {%d,%d,%d}, mask_bit = %d, opcode = 0x%x (%s), "
						"mask = %x, len = %d",
						header_len,
						h->fin, h->rsv1, h->rsv2, h->rsv3, h->mask_bit, 
						h->opcode, ws_opcode_str(h->opcode), h->mask, (int)h->payload_len);

					if (evbuffer_drain(in, header_len))
					{
						// TODO: Error! close
						LIBWS_LOG(LIBWS_ERR, "Failed to drain header buffer");
					}
					break;
				}
				case WS_PARSE_STATE_NEED_MORE:
					LIBWS_LOG(LIBWS_DEBUG2, " Need more header data");
					return;
				case WS_PARSE_STATE_ERROR:
					LIBWS_LOG(LIBWS_ERR, "Error protocol violation in header");
					ws_close_with_status(ws, WS_CLOSE_STATUS_PROTOCOL_ERR_1002);
					return;
				case WS_PARSE_STATE_USER_ABORT:
					// TODO: What to do here?
					LIBWS_LOG(LIBWS_ERR, "User abort");
					break;
			}

			_ws_handle_frame_begin(ws);
		}

		if (ws->has_header)
		{
			// We're in a frame.
			size_t recv_len = evbuffer_get_length(in);
			size_t remaining = (size_t)(ws->header.payload_len - ws->recv_frame_len);

			LIBWS_LOG(LIBWS_DEBUG2, "In frame (remaining %u bytes of %u payload)", 
					remaining, ws->header.payload_len);

			if (recv_len > remaining)
			{
				LIBWS_LOG(LIBWS_DEBUG2, "Received %u of %u remaining bytes", recv_len, remaining);
				recv_len = remaining;
			}

			if (remaining == 0)
			{
				_ws_handle_frame_end(ws);
			}
			else
			{
				int bytes_read;
				char *buf = (char *)_ws_malloc(recv_len);

				// TODO: Maybe we should only do evbuffer_pullup here instead
				// and pass that pointer on instead.
				bytes_read = evbuffer_remove(in, buf, recv_len);
				ws->recv_frame_len += bytes_read;

				if (bytes_read != recv_len)
				{
					LIBWS_LOG(LIBWS_ERR, "Wanted to read %u but only got %d", 
							recv_len, bytes_read);
				}

				LIBWS_LOG(LIBWS_DEBUG2, "read: %d (%llu of %llu bytes)", 
						bytes_read, ws->recv_frame_len, ws->header.payload_len);

				if (ws->header.mask_bit)
				{
					ws_unmask_payload(ws->header.mask, buf, bytes_read);
				}

				// Validate UTF8 text. Control frames are handled seperately.
				if (!ws->msg_isbinary 
				 && !WS_OPCODE_IS_CONTROL(ws->header.opcode))
				{
					LIBWS_LOG(LIBWS_DEBUG2, "About to validate UTF8, state = %d"
							" len = %d", ws->utf8_state, bytes_read);

					ws_utf8_validate(&ws->utf8_state, 
										buf, bytes_read);

					// Either the UTF8 is invalid, or a codepoint is not
					// complete in the finish frame.
					if ((ws->utf8_state == WS_UTF8_REJECT) 
					|| ((ws->utf8_state != WS_UTF8_ACCEPT) && (ws->header.fin)))
					{
						LIBWS_LOG(LIBWS_ERR, "Invalid UTF8!");

						ws_close_with_status(ws, 
							WS_CLOSE_STATUS_INCONSISTENT_DATA_1007);
					}

					LIBWS_LOG(LIBWS_DEBUG2, "Validated UTF8, state = %d", 
							ws->utf8_state);
				}

				if (_ws_handle_frame_data(ws, buf, bytes_read))
				{
					// TODO: Raise protocol error via error cb.
					// TODO: Close connection.
					LIBWS_LOG(LIBWS_ERR, "Failed to handle frame data");
				}
				else
				{
					// TODO: This is not hit in some cases.
					LIBWS_LOG(LIBWS_DEBUG2, "recv_frame_len = %llu, payload_len = %llu",
						 ws->recv_frame_len, ws->header.payload_len);
					// The entire frame has been received.
					if (ws->recv_frame_len == ws->header.payload_len)
					{
						_ws_handle_frame_end(ws);
					}
				}

				_ws_free(buf);
			}
		}
	}

	LIBWS_LOG(LIBWS_DEBUG, "    %lu bytes left after websocket read", 
			evbuffer_get_length(in));
}
コード例 #12
0
ファイル: bufferevent_sock.c プロジェクト: whm2300/libevent
static void
bufferevent_writecb(evutil_socket_t fd, short event, void *arg)
{
	struct bufferevent *bufev = arg;
	struct bufferevent_private *bufev_p =
	    EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
	int res = 0;
	short what = BEV_EVENT_WRITING;
	int connected = 0;
	ev_ssize_t atmost = -1;

	_bufferevent_incref_and_lock(bufev);

	if (event == EV_TIMEOUT) {
		/* Note that we only check for event==EV_TIMEOUT. If
		 * event==EV_TIMEOUT|EV_WRITE, we can safely ignore the
		 * timeout, since a read has occurred */
		what |= BEV_EVENT_TIMEOUT;
		goto error;
	}
	//正在连接服务器...
	if (bufev_p->connecting) {
		int c = evutil_socket_finished_connecting(fd);
		/* we need to fake the error if the connection was refused
		 * immediately - usually connection to localhost on BSD */
		if (bufev_p->connection_refused) {  //在bufferevent_socket_connect中被设置
		  bufev_p->connection_refused = 0;
		  c = -1;
		}

		if (c == 0) //正在连接,继续监听可写。
			goto done;

		bufev_p->connecting = 0;
		if (c < 0) {  //连接发生错误
			event_del(&bufev->ev_write);
			event_del(&bufev->ev_read);
			_bufferevent_run_eventcb(bufev, BEV_EVENT_ERROR);
			goto done;
		} else {  //连接成功
			connected = 1;
#ifdef WIN32
			if (BEV_IS_ASYNC(bufev)) {
				event_del(&bufev->ev_write);
				bufferevent_async_set_connected(bufev);
				_bufferevent_run_eventcb(bufev,
						BEV_EVENT_CONNECTED);
				goto done;
			}
#endif
            //连接成功,调用用户错误处理函数。比较奇怪。
			_bufferevent_run_eventcb(bufev,
					BEV_EVENT_CONNECTED);
			if (!(bufev->enabled & EV_WRITE) ||
			    bufev_p->write_suspended) {
				event_del(&bufev->ev_write);
				goto done;
			}
		}
	}

	atmost = _bufferevent_get_write_max(bufev_p);

    //写被挂起
	if (bufev_p->write_suspended)
		goto done;

    //存在可写数据
	if (evbuffer_get_length(bufev->output)) {
		evbuffer_unfreeze(bufev->output, 1);
		//将缓冲区数据写入socket。
		res = evbuffer_write_atmost(bufev->output, fd, atmost);
		evbuffer_freeze(bufev->output, 1);
		if (res == -1) {  //写发生错误
			int err = evutil_socket_geterror(fd);
			if (EVUTIL_ERR_RW_RETRIABLE(err))  //socket缓冲区满,一次未写完,继续监听可写事件,等待下次写入。
				goto reschedule;
			what |= BEV_EVENT_ERROR;  //写发生异常错误
		} else if (res == 0) {
			/* eof case
			   XXXX Actually, a 0 on write doesn't indicate
			   an EOF. An ECONNRESET might be more typical.
			 */
			what |= BEV_EVENT_EOF;
		}
		if (res <= 0)
			goto error;

		_bufferevent_decrement_write_buckets(bufev_p, res);
	}

    //缓冲区数据已写完,删除写事件。
	if (evbuffer_get_length(bufev->output) == 0) {
		event_del(&bufev->ev_write);
	}

	/* 低于写低水位,调用用户回调。
	 */
	if ((res || !connected) &&
	    evbuffer_get_length(bufev->output) <= bufev->wm_write.low) {
		_bufferevent_run_writecb(bufev);
	}

	goto done;

 reschedule:
	if (evbuffer_get_length(bufev->output) == 0) {
		event_del(&bufev->ev_write);
	}
	goto done;

 error:
	bufferevent_disable(bufev, EV_WRITE);
	_bufferevent_run_eventcb(bufev, what);

 done:
	_bufferevent_decref_and_unlock(bufev);
}
コード例 #13
0
ファイル: zhttpd.c プロジェクト: 734839030/zimg
/**
 * @brief get_request_cb The callback function of get a image request.
 *
 * @param req The request with a list of params and the md5 of image.
 * @param arg It is not useful.
 */
void get_request_cb(evhtp_request_t *req, void *arg)
{
    char *md5 = NULL, *fmt = NULL, *type = NULL;
    zimg_req_t *zimg_req = NULL;
	char *buff = NULL;
	size_t len;

    evhtp_connection_t *ev_conn = evhtp_request_get_connection(req);
    struct sockaddr *saddr = ev_conn->saddr;
    struct sockaddr_in *ss = (struct sockaddr_in *)saddr;
    char address[16];

    const char *xff_address = evhtp_header_find(req->headers_in, "X-Forwarded-For");
    if(xff_address)
    {
        inet_aton(xff_address, &ss->sin_addr);
    }
    strncpy(address, inet_ntoa(ss->sin_addr), 16);

    int req_method = evhtp_request_get_method(req);
    if(req_method >= 16)
        req_method = 16;
    LOG_PRINT(LOG_DEBUG, "Method: %d", req_method);
    if(strcmp(method_strmap[req_method], "POST") == 0)
    {
        LOG_PRINT(LOG_DEBUG, "POST Request.");
        post_request_cb(req, NULL);
        return;
    }
	else if(strcmp(method_strmap[req_method], "GET") != 0)
    {
        LOG_PRINT(LOG_DEBUG, "Request Method Not Support.");
        LOG_PRINT(LOG_INFO, "%s refuse method", address);
        goto err;
    }

    if(settings.down_access != NULL)
    {
        int acs = zimg_access_inet(settings.down_access, ss->sin_addr.s_addr);
        LOG_PRINT(LOG_DEBUG, "access check: %d", acs);

        if(acs == ZIMG_FORBIDDEN)
        {
            LOG_PRINT(LOG_DEBUG, "check access: ip[%s] forbidden!", address);
            LOG_PRINT(LOG_INFO, "%s refuse get forbidden", address);
            goto forbidden;
        }
        else if(acs == ZIMG_ERROR)
        {
            LOG_PRINT(LOG_DEBUG, "check access: check ip[%s] failed!", address);
            LOG_PRINT(LOG_ERROR, "%s fail get access", address);
            goto err;
        }
    }

	const char *uri;
	uri = req->uri->path->full;

    if(strlen(uri) == 1 && uri[0] == '/')
    {
        LOG_PRINT(LOG_DEBUG, "Root Request.");
        int fd = -1;
        struct stat st;
        if((fd = open(settings.root_path, O_RDONLY)) == -1)
        {
            LOG_PRINT(LOG_DEBUG, "Root_page Open Failed. Return Default Page.");
            evbuffer_add_printf(req->buffer_out, "<html>\n<body>\n<h1>\nWelcome To zimg World!</h1>\n</body>\n</html>\n");
        }
        else
        {
            if (fstat(fd, &st) < 0)
            {
                /* Make sure the length still matches, now that we
                 * opened the file :/ */
                LOG_PRINT(LOG_DEBUG, "Root_page Length fstat Failed. Return Default Page.");
                evbuffer_add_printf(req->buffer_out, "<html>\n<body>\n<h1>\nWelcome To zimg World!</h1>\n</body>\n</html>\n");
            }
            else
            {
                evbuffer_add_file(req->buffer_out, fd, 0, st.st_size);
            }
        }
        //evbuffer_add_printf(req->buffer_out, "<html>\n </html>\n");
        evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
        evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0));
        evhtp_send_reply(req, EVHTP_RES_OK);
        LOG_PRINT(LOG_DEBUG, "============get_request_cb() DONE!===============");
        LOG_PRINT(LOG_INFO, "%s succ root page", address);
        goto done;
    }

    if(strstr(uri, "favicon.ico"))
    {
        LOG_PRINT(LOG_DEBUG, "favicon.ico Request, Denied.");
        evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
        evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0));
        zimg_headers_add(req, settings.headers);
        evhtp_send_reply(req, EVHTP_RES_OK);
        goto done;
    }
	LOG_PRINT(LOG_DEBUG, "Got a GET request for <%s>",  uri);

	/* Don't allow any ".."s in the path, to avoid exposing stuff outside
	 * of the docroot.  This test is both overzealous and underzealous:
	 * it forbids aceptable paths like "/this/one..here", but it doesn't
	 * do anything to prevent symlink following." */
	if (strstr(uri, ".."))
    {
        LOG_PRINT(LOG_DEBUG, "attempt to upper dir!");
        LOG_PRINT(LOG_INFO, "%s refuse directory", address);
		goto forbidden;
    }

    size_t md5_len = strlen(uri) + 1;
    md5 = (char *)malloc(md5_len);
    if(md5 == NULL)
    {
        LOG_PRINT(LOG_DEBUG, "md5 malloc failed!");
        LOG_PRINT(LOG_ERROR, "%s fail malloc", address);
        goto err;
    }
    if(uri[0] == '/')
        str_lcpy(md5, uri+1, md5_len);
    else
        str_lcpy(md5, uri, md5_len);
	LOG_PRINT(LOG_DEBUG, "md5 of request is <%s>",  md5);
    if(is_md5(md5) == -1)
    {
        LOG_PRINT(LOG_DEBUG, "Url is Not a zimg Request.");
        LOG_PRINT(LOG_INFO, "%s refuse url illegal", address);
        goto err;
    }
	/* This holds the content we're sending. */

    evthr_t *thread = get_request_thr(req);
    thr_arg_t *thr_arg = (thr_arg_t *)evthr_get_aux(thread);

    int width, height, proportion, gray, x, y, rotate, quality, sv;
    width = 0;
    height = 0;
    proportion = 1;
    gray = 0;
    x = -1;
    y = -1;
    rotate = 0;
    quality = 0;
    sv = 0;

    evhtp_kvs_t *params;
    params = req->uri->query;
    if(params != NULL)
    {
        if(settings.disable_args != 1)
        {
            const char *str_w = evhtp_kv_find(params, "w");
            const char *str_h = evhtp_kv_find(params, "h");
            width = (str_w) ? atoi(str_w) : 0;
            height = (str_h) ? atoi(str_h) : 0;

            const char *str_p = evhtp_kv_find(params, "p");
            proportion = (str_p) ? atoi(str_p) : 1;

            const char *str_g = evhtp_kv_find(params, "g");
            gray = (str_g) ? atoi(str_g) : 0;

            const char *str_x = evhtp_kv_find(params, "x");
            const char *str_y = evhtp_kv_find(params, "y");
            x = (str_x) ? atoi(str_x) : -1;
            y = (str_y) ? atoi(str_y) : -1;

            if(x != -1 || y != -1)
            {
                proportion = 1;
            }

            const char *str_r = evhtp_kv_find(params, "r");
            rotate = (str_r) ? atoi(str_r) : 0;

            const char *str_q = evhtp_kv_find(params, "q");
            quality = (str_q) ? atoi(str_q) : 0;

            const char *str_f = evhtp_kv_find(params, "f");
            if(str_f)
            {
                size_t fmt_len = strlen(str_f) + 1;
                fmt = (char *)malloc(fmt_len);
                if(fmt != NULL)
                    str_lcpy(fmt, str_f, fmt_len);
                LOG_PRINT(LOG_DEBUG, "fmt = %s", fmt);
            }
        }

        if(settings.disable_type != 1)
        {
            const char *str_t = evhtp_kv_find(params, "t");
            if(str_t)
            {
                size_t type_len = strlen(str_t) + 1;
                type = (char *)malloc(type_len);
                if(type != NULL)
                    str_lcpy(type, str_t, type_len);
                LOG_PRINT(LOG_DEBUG, "type = %s", type);
            }
        }
    }
    else
    {
        sv = 1;
    }

    quality = (quality != 0 ? quality : settings.quality);
    zimg_req = (zimg_req_t *)malloc(sizeof(zimg_req_t)); 
    if(zimg_req == NULL)
    {
        LOG_PRINT(LOG_DEBUG, "zimg_req malloc failed!");
        LOG_PRINT(LOG_ERROR, "%s fail malloc", address);
        goto err;
    }
    zimg_req -> md5 = md5;
    zimg_req -> type = type;
    zimg_req -> width = width;
    zimg_req -> height = height;
    zimg_req -> proportion = proportion;
    zimg_req -> gray = gray;
    zimg_req -> x = x;
    zimg_req -> y = y;
    zimg_req -> rotate = rotate;
    zimg_req -> quality = quality;
    zimg_req -> fmt = (fmt != NULL ? fmt : settings.format);
    zimg_req -> sv = sv;
    zimg_req -> thr_arg = thr_arg;

    int get_img_rst = -1;
    get_img_rst = settings.get_img(zimg_req, req);

    if(get_img_rst == -1)
    {
        LOG_PRINT(LOG_DEBUG, "zimg Requset Get Image[MD5: %s] Failed!", zimg_req->md5);
        if(type)
            LOG_PRINT(LOG_ERROR, "%s fail pic:%s t:%s", address, md5, type);
        else
            LOG_PRINT(LOG_ERROR, "%s fail pic:%s w:%d h:%d p:%d g:%d x:%d y:%d r:%d q:%d f:%s",
                address, md5, width, height, proportion, gray, x, y, rotate, quality, zimg_req->fmt); 
        goto err;
    }
    if(get_img_rst == 2)
    {
        LOG_PRINT(LOG_DEBUG, "Etag Matched Return 304 EVHTP_RES_NOTMOD.");
        if(type)
            LOG_PRINT(LOG_INFO, "%s succ 304 pic:%s t:%s", address, md5, type);
        else
            LOG_PRINT(LOG_INFO, "%s succ 304 pic:%s w:%d h:%d p:%d g:%d x:%d y:%d r:%d q:%d f:%s",
                address, md5, width, height, proportion, gray, x, y, rotate, quality, zimg_req->fmt); 
        evhtp_send_reply(req, EVHTP_RES_NOTMOD);
        goto done;
    }

    len = evbuffer_get_length(req->buffer_out);
    LOG_PRINT(LOG_DEBUG, "get buffer length: %d", len);

    LOG_PRINT(LOG_DEBUG, "Got the File!");
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "image/jpeg", 0, 0));
    zimg_headers_add(req, settings.headers);
    evhtp_send_reply(req, EVHTP_RES_OK);
    if(type)
        LOG_PRINT(LOG_INFO, "%s succ pic:%s t:%s size:%d", address, md5, type, len); 
    else
        LOG_PRINT(LOG_INFO, "%s succ pic:%s w:%d h:%d p:%d g:%d x:%d y:%d r:%d q:%d f:%s size:%d", 
                address, md5, width, height, proportion, gray, x, y, rotate, quality, zimg_req->fmt, 
                len);
    LOG_PRINT(LOG_DEBUG, "============get_request_cb() DONE!===============");
    goto done;

forbidden:
    evbuffer_add_printf(req->buffer_out, "<html><body><h1>403 Forbidden!</h1></body></html>"); 
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0));
    evhtp_send_reply(req, EVHTP_RES_FORBIDDEN);
    LOG_PRINT(LOG_DEBUG, "============get_request_cb() FORBIDDEN!===============");
    goto done;

err:
    evbuffer_add_printf(req->buffer_out, "<html><body><h1>404 Not Found!</h1></body></html>");
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0));
    evhtp_send_reply(req, EVHTP_RES_NOTFOUND);
    LOG_PRINT(LOG_DEBUG, "============get_request_cb() ERROR!===============");

done:
    free(fmt);
    free(md5);
    free(type);
    free(zimg_req);
    free(buff);
}
コード例 #14
0
ファイル: zhttpd.c プロジェクト: 734839030/zimg
/**
 * @brief post_request_cb The callback function of a POST request to upload a image.
 *
 * @param req The request with image buffer.
 * @param arg It is not useful.
 */
void post_request_cb(evhtp_request_t *req, void *arg)
{
    int post_size = 0;
    char *buff = NULL;
    int err_no = 0;
    int ret_json = 1;

    evhtp_connection_t *ev_conn = evhtp_request_get_connection(req);
    struct sockaddr *saddr = ev_conn->saddr;
    struct sockaddr_in *ss = (struct sockaddr_in *)saddr;
    char address[16];

    const char *xff_address = evhtp_header_find(req->headers_in, "X-Forwarded-For");
    if(xff_address)
    {
        inet_aton(xff_address, &ss->sin_addr);
    }
    strncpy(address, inet_ntoa(ss->sin_addr), 16);

    int req_method = evhtp_request_get_method(req);
    if(req_method >= 16)
        req_method = 16;
    LOG_PRINT(LOG_DEBUG, "Method: %d", req_method);
    if(strcmp(method_strmap[req_method], "POST") != 0)
    {
        LOG_PRINT(LOG_DEBUG, "Request Method Not Support.");
        LOG_PRINT(LOG_INFO, "%s refuse post method", address);
        err_no = 2;
        goto err;
    }

    if(settings.up_access != NULL)
    {
        int acs = zimg_access_inet(settings.up_access, ss->sin_addr.s_addr);
        LOG_PRINT(LOG_DEBUG, "access check: %d", acs);
        if(acs == ZIMG_FORBIDDEN)
        {
            LOG_PRINT(LOG_DEBUG, "check access: ip[%s] forbidden!", address);
            LOG_PRINT(LOG_INFO, "%s refuse post forbidden", address);
            err_no = 3;
            goto forbidden;
        }
        else if(acs == ZIMG_ERROR)
        {
            LOG_PRINT(LOG_DEBUG, "check access: check ip[%s] failed!", address);
            LOG_PRINT(LOG_ERROR, "%s fail post access %s", address);
            err_no = 0;
            goto err;
        }
    }

    const char *content_len = evhtp_header_find(req->headers_in, "Content-Length");
    if(!content_len)
    {
        LOG_PRINT(LOG_DEBUG, "Get Content-Length error!");
        LOG_PRINT(LOG_ERROR, "%s fail post content-length", address);
        err_no = 5;
        goto err;
    }
    post_size = atoi(content_len);
    if(post_size <= 0)
    {
        LOG_PRINT(LOG_DEBUG, "Image Size is Zero!");
        LOG_PRINT(LOG_ERROR, "%s fail post empty", address);
        err_no = 5;
        goto err;
    }
    if(post_size > settings.max_size)
    {
        LOG_PRINT(LOG_DEBUG, "Image Size Too Large!");
        LOG_PRINT(LOG_ERROR, "%s fail post large", address);
        err_no = 7;
        goto err;
    }
    const char *content_type = evhtp_header_find(req->headers_in, "Content-Type");
    if(!content_type)
    {
        LOG_PRINT(LOG_DEBUG, "Get Content-Type error!");
        LOG_PRINT(LOG_ERROR, "%s fail post content-type", address);
        err_no = 6;
        goto err;
    }
	evbuf_t *buf;
    buf = req->buffer_in;
    buff = (char *)malloc(post_size);
    if(buff == NULL)
    {
        LOG_PRINT(LOG_DEBUG, "buff malloc failed!");
        LOG_PRINT(LOG_ERROR, "%s fail malloc buff", address);
        err_no = 0;
        goto err;
    }
    int rmblen, evblen;
    if(evbuffer_get_length(buf) <= 0)
    {
        LOG_PRINT(LOG_DEBUG, "Empty Request!");
        LOG_PRINT(LOG_ERROR, "%s fail post empty", address);
        err_no = 4;
        goto err;
    }
    while((evblen = evbuffer_get_length(buf)) > 0)
    {
        LOG_PRINT(LOG_DEBUG, "evblen = %d", evblen);
        rmblen = evbuffer_remove(buf, buff, evblen);
        LOG_PRINT(LOG_DEBUG, "rmblen = %d", rmblen);
        if(rmblen < 0)
        {
            LOG_PRINT(LOG_DEBUG, "evbuffer_remove failed!");
            LOG_PRINT(LOG_ERROR, "%s fail post parse", address);
            err_no = 4;
            goto err;
        }
    }
    if(strstr(content_type, "multipart/form-data") == NULL)
    {
        err_no = binary_parse(req, content_type, address, buff, post_size);
    }
    else
    {
        ret_json = 0;
        err_no = multipart_parse(req, content_type, address, buff, post_size);
    }
    if(err_no != -1)
    {
        goto err;
    }
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
    evhtp_send_reply(req, EVHTP_RES_OK);
    LOG_PRINT(LOG_DEBUG, "============post_request_cb() DONE!===============");
    goto done;

forbidden:
    json_return(req, err_no, NULL, 0);
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
    evhtp_send_reply(req, EVHTP_RES_OK);
    LOG_PRINT(LOG_DEBUG, "============post_request_cb() FORBIDDEN!===============");
    goto done;

err:
    if(ret_json == 0)
    {
        evbuffer_add_printf(req->buffer_out, "<h1>Upload Failed!</h1></body></html>"); 
        evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0));
    }
    else
    {
        json_return(req, err_no, NULL, 0);
    }
    evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1));
    evhtp_send_reply(req, EVHTP_RES_OK);
    LOG_PRINT(LOG_DEBUG, "============post_request_cb() ERROR!===============");

done:
    free(buff);
}
コード例 #15
0
ファイル: threadsay.c プロジェクト: wadee/go_proj
//void drive_machine(conn* c){
//改成bufferevent之后event_handler和drive_machine都不能幸免需要改参数
void drive_machine(conn* c, struct bufferevent * incoming){
    assert(c != NULL);
    // 真正的处理函数,根据不同的conn的状态来进行不同的处理。
    // 虽然我做这个demo只是把消息回显而已,但貌似这么多种状态还是得处理。
    bool stop = false;
    int sfd;

    socklen_t addrlen;
    struct sockaddr_storage addr;
    struct evbuffer *evreturn;
    char *req;

    while(!stop){
        switch(c->state){
            case conn_listening:
                //如果是listenting状态,则需要把连接accept
                addrlen = sizeof(addr);
                sfd = accept(c->sfd, (struct sockaddr *)&addr, &addrlen);
                if (sfd == -1)
                {
                    // accept错误
                    perror("sfd accept failed");
                    accept_new_conns(false); //用来决定主线程是否还需要accept连接,如果已经接近饱和了,就停住,等一个时间间隔再来试。
                    stop = true;
                }
                //分派conn任务
                dispatch_conn_new(sfd, conn_new_cmd, EV_READ | EV_PERSIST,
                                     DATA_BUFFER_SIZE, tcp_transport);
                stop = true;
                break;
            case conn_new_cmd:
                /* fall through */
            case conn_read:
                /*  now try reading from the socket */
                req = evbuffer_readline(incoming->input); 
                if (req == NULL){
                    //conn_set_state(c, conn_closing);
                    //goto set_conn_closing;
                    conn_set_state(c, conn_waiting);
                    break;    
                }
                if(c->req != NULL){
                    free(c->req);
                    c->req = NULL;
                }
                c->req = req;
                conn_set_state(c, conn_mwrite);
		//if (!update_event(c, EV_WRITE | EV_PERSIST)){
		//	printf("conn_read update event failed");
		//	goto set_conn_closing;
		//}
		//stop = true;
		//stop = true;
                break;
                //evreturn = evbuffer_new();
                //evbuffer_add_printf(evreturn, "You said %s\n", req);
               // bufferevent_write_buffer(incoming, evreturn);
                //evbuffer_free(evreturn);
                //free(req);

            set_conn_closing: 
                conn_set_state(c, conn_closing);
                break;
            case conn_mwrite:
                //所有的回复到在这个函数进行输出
                req = c->req;
                evreturn = evbuffer_new();
	//	bufferevent_setwatermark(incoming, EV_WRITE, 0, 0);
               int res1 =  evbuffer_add_printf(evreturn, "You said %s\n", req);
               int res2 =  bufferevent_write_buffer(incoming, evreturn);
//		int res3 = bufferevent_flush(incoming, EV_WRITE, BEV_FLUSH);
		int res4 = evbuffer_get_length(incoming->output);
                evbuffer_free(evreturn);
                free(req);
		evreturn = NULL;
		//int fd = (int)bufferevent_getfd(incoming);
		//char buf[20];
		//
		//sprintf(buf, "You said %s\n", req);
		//write(fd, buf, 11);
                c->req = NULL;
                conn_set_state(c,conn_waiting);
		stop = true;
                break;
            case conn_waiting:
                if (!update_event(c, EV_READ | EV_PERSIST)) {
                    fprintf(stderr, "Couldn't update event\n");
                    conn_set_state(c, conn_closing);
                    break;
                }
                conn_set_state(c, conn_read);
                stop = true;
                break;
            case conn_closing:
                conn_close(c);
                stop = true;
                break;
            }
                /* otherwise we have a real error, on which we close the connection */
        }

}
コード例 #16
0
ファイル: Buffer.c プロジェクト: gmoonen/craftd
size_t
CD_BufferLength (CDBuffer* self)
{
    return evbuffer_get_length(self->raw);
}
コード例 #17
0
ファイル: bufferevent_sock.c プロジェクト: whm2300/libevent
static void
bufferevent_readcb(evutil_socket_t fd, short event, void *arg)
{
	struct bufferevent *bufev = arg;
	struct bufferevent_private *bufev_p =
	    EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
	struct evbuffer *input;
	int res = 0;
	short what = BEV_EVENT_READING;
	ev_ssize_t howmuch = -1, readmax=-1;

	_bufferevent_incref_and_lock(bufev);

	if (event == EV_TIMEOUT) {
		/* Note that we only check for event==EV_TIMEOUT. If
		 * event==EV_TIMEOUT|EV_READ, we can safely ignore the
		 * timeout, since a read has occurred */
		what |= BEV_EVENT_TIMEOUT;
		goto error;
	}

	input = bufev->input;

	/*
	 * If we have a high watermark configured then we don't want to
	 * read more data than would make us reach the watermark.
	 */
	if (bufev->wm_read.high != 0) {
		howmuch = bufev->wm_read.high - evbuffer_get_length(input);
		/* 缓冲区超过高水位,挂起读。 */
		if (howmuch <= 0) {
			bufferevent_wm_suspend_read(bufev);
			goto done;
		}
	}
	
	//因为用户可以限速,所以这么要检测最大的可读大小。  
    //如果没有限速的话,那么将返回16384字节,即16K  
    //默认情况下是没有限速的。  
	readmax = _bufferevent_get_read_max(bufev_p);
	if (howmuch < 0 || howmuch > readmax) /* The use of -1 for "unlimited"
					       * uglifies this code. XXXX */
		howmuch = readmax;
	if (bufev_p->read_suspended)
		goto done;

	evbuffer_unfreeze(input, 0);
	res = evbuffer_read(input, fd, (int)howmuch); /* XXXX evbuffer_read would do better to take and return ev_ssize_t */
	evbuffer_freeze(input, 0);

	if (res == -1) {
		int err = evutil_socket_geterror(fd);
		if (EVUTIL_ERR_RW_RETRIABLE(err))  //EINTER or EAGAIN 
			goto reschedule;
		/* error case */
		what |= BEV_EVENT_ERROR;
	} else if (res == 0) {
		/* eof case */
		what |= BEV_EVENT_EOF;
	}

	if (res <= 0)
		goto error;

	_bufferevent_decrement_read_buckets(bufev_p, res);

	/* 数据大于低水平,调用用户设置的回调。 */
	if (evbuffer_get_length(input) >= bufev->wm_read.low)
		_bufferevent_run_readcb(bufev);

	goto done;

 reschedule:
	goto done;

 error:
	bufferevent_disable(bufev, EV_READ);
	_bufferevent_run_eventcb(bufev, what);

 done:
	_bufferevent_decref_and_unlock(bufev);
}
コード例 #18
0
ファイル: show.c プロジェクト: Javierortizc/transmission
static void
doScrape (const tr_info * inf)
{
  unsigned int i;

  for (i=0; i<inf->trackerCount; ++i)
    {
      CURL * curl;
      CURLcode res;
      struct evbuffer * buf;
      const char * scrape = inf->trackers[i].scrape;
      char * url;
      char escaped[SHA_DIGEST_LENGTH*3 + 1];

      if (scrape == NULL)
        continue;

      tr_http_escape_sha1 (escaped, inf->hash);

      url = tr_strdup_printf ("%s%cinfo_hash=%s",
                              scrape,
                              strchr (scrape, '?') ? '&' : '?',
                              escaped);

      printf ("%s ... ", url);
      fflush (stdout);

      buf = evbuffer_new ();
      curl = tr_curl_easy_init (buf);
      curl_easy_setopt (curl, CURLOPT_URL, url);
      curl_easy_setopt (curl, CURLOPT_TIMEOUT, TIMEOUT_SECS);

      if ((res = curl_easy_perform (curl)))
        {
          printf ("error: %s\n", curl_easy_strerror (res));
        }
      else
        {
          long response;
          curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &response);
          if (response != 200)
            {
              printf ("error: unexpected response %ld \"%s\"\n",
                      response,
                      tr_webGetResponseStr (response));
            }
          else /* HTTP OK */
            {
              tr_variant top;
              tr_variant * files;
              bool matched = false;
              const char * begin = (const char*) evbuffer_pullup (buf, -1);

              if (!tr_variantFromBenc (&top, begin, evbuffer_get_length(buf)))
                {
                  if (tr_variantDictFindDict (&top, TR_KEY_files, &files))
                    {
                      int i = 0;
                      tr_quark key;
                      tr_variant * val;

                      while (tr_variantDictChild (files, i++, &key, &val))
                        {
                          if (memcmp (inf->hash, tr_quark_get_string (key, NULL), SHA_DIGEST_LENGTH) == 0)
                            {
                              int64_t seeders = -1;
                              int64_t leechers = -1;
                              tr_variantDictFindInt (val, TR_KEY_complete, &seeders);
                              tr_variantDictFindInt (val, TR_KEY_incomplete, &leechers);
                              printf ("%d seeders, %d leechers\n", (int)seeders, (int)leechers);
                              matched = true;
                            }
                        }
                    }

                  tr_variantFree (&top);
                }

              if (!matched)
                printf ("no match\n");
            }
        }

      curl_easy_cleanup (curl);
      evbuffer_free (buf);
      tr_free (url);
    }
}
コード例 #19
0
ファイル: regress_buffer.c プロジェクト: rphillips/libevent
static void
test_evbuffer(void *ptr)
{
	static char buffer[512], *tmp;
	struct evbuffer *evb = evbuffer_new();
	struct evbuffer *evb_two = evbuffer_new();
	size_t sz_tmp;
	int i;

	evbuffer_validate(evb);
	evbuffer_add_printf(evb, "%s/%d", "hello", 1);
	evbuffer_validate(evb);

	tt_assert(evbuffer_get_length(evb) == 7);
	tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "hello/1", 1));

	evbuffer_add_buffer(evb, evb_two);
	evbuffer_validate(evb);

	evbuffer_drain(evb, strlen("hello/"));
	evbuffer_validate(evb);
	tt_assert(evbuffer_get_length(evb) == 1);
	tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1", 1));

	evbuffer_add_printf(evb_two, "%s", "/hello");
	evbuffer_validate(evb);
	evbuffer_add_buffer(evb, evb_two);
	evbuffer_validate(evb);

	tt_assert(evbuffer_get_length(evb_two) == 0);
	tt_assert(evbuffer_get_length(evb) == 7);
	tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1/hello", 7) != 0);

	memset(buffer, 0, sizeof(buffer));
	evbuffer_add(evb, buffer, sizeof(buffer));
	evbuffer_validate(evb);
	tt_assert(evbuffer_get_length(evb) == 7 + 512);

	tmp = (char *)evbuffer_pullup(evb, 7 + 512);
	tt_assert(tmp);
	tt_assert(!strncmp(tmp, "1/hello", 7));
	tt_assert(!memcmp(tmp + 7, buffer, sizeof(buffer)));
	evbuffer_validate(evb);

	evbuffer_prepend(evb, "something", 9);
	evbuffer_validate(evb);
	evbuffer_prepend(evb, "else", 4);
	evbuffer_validate(evb);

	tmp = (char *)evbuffer_pullup(evb, 4 + 9 + 7);
	tt_assert(!strncmp(tmp, "elsesomething1/hello", 4 + 9 + 7));
	evbuffer_validate(evb);

	evbuffer_drain(evb, -1);
	evbuffer_validate(evb);
	evbuffer_drain(evb_two, -1);
	evbuffer_validate(evb);

	for (i = 0; i < 3; ++i) {
		evbuffer_add(evb_two, buffer, sizeof(buffer));
		evbuffer_validate(evb_two);
		evbuffer_add_buffer(evb, evb_two);
		evbuffer_validate(evb);
		evbuffer_validate(evb_two);
	}

	tt_assert(evbuffer_get_length(evb_two) == 0);
	tt_assert(evbuffer_get_length(evb) == i * sizeof(buffer));

	/* test remove buffer */
	sz_tmp = (size_t)(sizeof(buffer)*2.5);
	evbuffer_remove_buffer(evb, evb_two, sz_tmp);
	tt_assert(evbuffer_get_length(evb_two) == sz_tmp);
	tt_assert(evbuffer_get_length(evb) == sizeof(buffer) / 2);
	evbuffer_validate(evb);

	if (memcmp(evbuffer_pullup(
			   evb, -1), buffer, sizeof(buffer) / 2) != 0 ||
	    memcmp(evbuffer_pullup(
			   evb_two, -1), buffer, sizeof(buffer) != 0))
		tt_abort_msg("Pullup did not preserve content");

	evbuffer_validate(evb);


	/* testing one-vector reserve and commit */
	{
		struct evbuffer_iovec v[1];
		char *buf;
		int i, j, r;

		for (i = 0; i < 3; ++i) {
			r = evbuffer_reserve_space(evb, 10000, v, 1);
			tt_int_op(r, ==, 1);
			tt_assert(v[0].iov_len >= 10000);
			tt_assert(v[0].iov_base != NULL);

			evbuffer_validate(evb);
			buf = v[0].iov_base;
			for (j = 0; j < 10000; ++j) {
				buf[j] = j;
			}
			evbuffer_validate(evb);

			tt_int_op(evbuffer_commit_space(evb, v, 1), ==, 0);
			evbuffer_validate(evb);

			tt_assert(evbuffer_get_length(evb) >= 10000);

			evbuffer_drain(evb, j * 5000);
			evbuffer_validate(evb);
		}
	}

 end:
	evbuffer_free(evb);
	evbuffer_free(evb_two);
}
コード例 #20
0
ファイル: stream.c プロジェクト: imasahiro/logpool-v2
static int chunk_stream_size(struct chunk_stream *cs)
{
    return evbuffer_get_length(bufferevent_get_input(cs->bev));
}
コード例 #21
0
ファイル: LookingGlass.c プロジェクト: novag/LookingGlass
static void on_read(struct bufferevent *bev, void *ctx) {
    struct evbuffer *input;
    int fd;
    size_t len;

    char *line;
    char *emsg;

    char **argv = malloc(sizeof(char *));
    int argc = 0;
    char *arg_ptr, *save_ptr;

    /*
     * 1: Unknown command
     * 2: Too few arguments
     * 3: Internal error
     * 4: Missing command
     */
    int status;
    int i;

    input = bufferevent_get_input(bev);
    fd = bufferevent_getfd(bev);

    len = evbuffer_get_length(input);
    line = malloc(len + 1);
    evbuffer_copyout(input, line, len);

    if (len == 0) {
        status = 4;
        goto END;
    }

    if (line[len - 1] == '\n') {
        line[len - 1] = 0;
    } else {
        line[len] = 0;
    }

    arg_ptr = strtok_r(line, " ", &save_ptr);
    while (arg_ptr != NULL) {
        len = strlen(arg_ptr) + 1;

        argv[argc] = malloc(len);
        strncpy(argv[argc], arg_ptr, len);
        argv = realloc(argv, argc + 1);

        arg_ptr = strtok_r(NULL, " ", &save_ptr);

        argc++;
    }

    printf("%s LookingGlass: Received command \"%s\" with %d arguments", date(), argv[0], argc - 1);
    for (i = 1; i < argc; i++) {
        printf(" %d:\"%s\"", i, argv[i]);
    }
    printf(".\n");

    status = call_function(argv[0], fd, argc, argv);

END:
    switch (status) {
    case 1:
        emsg = "Unknown command";
        write(fd, emsg, strlen(emsg));
        fprintf(stdout, "%s LookingGlass: Error: Disconnecting client. Reason: %s: %s.\n", date(), emsg, argv[0]);
        break;
    case 2:
        emsg = "Too few arguments";
        write(fd, emsg, strlen(emsg));
        fprintf(stdout, "%s LookingGlass: Disconnecting client. Error: %s.\n", date(), emsg);
        break;
    case 3:
        emsg = "Internal error";
        write(fd, emsg, strlen(emsg));
        fprintf(stdout, "%s LookingGlass: Disconnecting client. Error: %s.\n", date(), emsg);
        break;
    case 4:
        emsg = "Missing command";
        write(fd, emsg, strlen(emsg));
        fprintf(stdout, "%s LookingGlass: Disconnecting client. Error: %s.\n", date(), emsg);
        break;
    default:
        printf("%s LookingGlass: Disconnecting client.\n", date());
        break;
    }

    bufferevent_free(bev);

    for (i = 0; i < argc; i++) {
        free(argv[i]);
    }
    free(argv);
    free(line);
}
コード例 #22
0
static void static_dump_request_cb(struct evhttp_request *req, void *arg)
{

	const char *cmdtype;
	struct evkeyvalq *headers;
	struct evkeyval *header;
	struct evbuffer *buf;


	switch (evhttp_request_get_command(req)) {
		case EVHTTP_REQ_GET:
			cmdtype = "GET";
		break;
		case EVHTTP_REQ_POST:
			cmdtype = "POST";
		break;
		default:
			cmdtype = "unknown";
		break;
	}
	printf("Received a %s request for %s\nHeaders:\n",
	    cmdtype, evhttp_request_get_uri(req));

	headers = evhttp_request_get_input_headers(req);
	for (header = headers->tqh_first; header;
	    header = header->next.tqe_next) {
		printf("  %s: %s\n", header->key, header->value);
	}

	buf = evhttp_request_get_input_buffer(req);
	puts("Input data: <<<");
	printf("len:%d", evbuffer_get_length(buf));

	/*
	while (evbuffer_get_length(buf)) {
		int n;
		char cbuf[128];
		n = evbuffer_remove(buf, cbuf, sizeof(buf)-1);
		if (n > 0)
			(void) fwrite(cbuf, 1, n, stdout);
	}
	puts(">>>");
	*/

	//get params
	struct evkeyvalq *query_params_ptr = calloc(sizeof(struct evkeyvalq), 1);
	getParams(req, query_params_ptr);
	char *test = NULL;
	test = getParam(query_params_ptr, "test");
	if (test != NULL) {
		fprintf(stderr, "param test: %s", test);
	}
	evhttp_clear_headers(query_params_ptr);
	free(test);


	//post params
	struct evkeyvalq *post_params_ptr = calloc(sizeof(struct evkeyvalq), 1);
	postParams(req, post_params_ptr);
	char *name = NULL;
	name = postParam(post_params_ptr, "name");
	if (name != NULL) {
		fprintf(stderr, "param name: %s", name);
	}

	evhttp_clear_headers(post_params_ptr);
	free(name);

	evhttp_send_reply(req, 200, "OK", NULL);

	//evhttp_request_free(req);
}
コード例 #23
0
ファイル: bufferevent_sock.c プロジェクト: NeilHappy/libevent
static void
bufferevent_writecb(evutil_socket_t fd, short event, void *arg)
{
	struct bufferevent *bufev = arg;
	struct bufferevent_private *bufev_p =
	    EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
	int res = 0;
	short what = BEV_EVENT_WRITING;
	int connected = 0;
	ev_ssize_t atmost = -1;

	bufferevent_incref_and_lock_(bufev);

	if (event == EV_TIMEOUT) {
		/* Note that we only check for event==EV_TIMEOUT. If
		 * event==EV_TIMEOUT|EV_WRITE, we can safely ignore the
		 * timeout, since a read has occurred */
		what |= BEV_EVENT_TIMEOUT;
		goto error;
	}
	if (bufev_p->connecting) {
		int c = evutil_socket_finished_connecting_(fd);
		/* we need to fake the error if the connection was refused
		 * immediately - usually connection to localhost on BSD */
		if (bufev_p->connection_refused) {
		  bufev_p->connection_refused = 0;
		  c = -1;
		}

		if (c == 0)
			goto done;

		bufev_p->connecting = 0;
		if (c < 0) {
			event_del(&bufev->ev_write);
			event_del(&bufev->ev_read);
			bufferevent_run_eventcb_(bufev, BEV_EVENT_ERROR);
			goto done;
		} else {
			connected = 1;
#ifdef _WIN32
			if (BEV_IS_ASYNC(bufev)) {
				event_del(&bufev->ev_write);
				bufferevent_async_set_connected_(bufev);
				bufferevent_run_eventcb_(bufev,
						BEV_EVENT_CONNECTED);
				goto done;
			}
#endif
			bufferevent_run_eventcb_(bufev,
					BEV_EVENT_CONNECTED);
			if (!(bufev->enabled & EV_WRITE) ||
			    bufev_p->write_suspended) {
				event_del(&bufev->ev_write);
				goto done;
			}
		}
	}

	atmost = bufferevent_get_write_max_(bufev_p);

	if (bufev_p->write_suspended)
		goto done;

	if (evbuffer_get_length(bufev->output)) {
		evbuffer_unfreeze(bufev->output, 1);
		res = evbuffer_write_atmost(bufev->output, fd, atmost);
		evbuffer_freeze(bufev->output, 1);
		if (res == -1) {
			int err = evutil_socket_geterror(fd);
			if (EVUTIL_ERR_RW_RETRIABLE(err))
				goto reschedule;
			what |= BEV_EVENT_ERROR;
		} else if (res == 0) {
			/* eof case
			   XXXX Actually, a 0 on write doesn't indicate
			   an EOF. An ECONNRESET might be more typical.
			 */
			what |= BEV_EVENT_EOF;
		}
		if (res <= 0)
			goto error;

		bufferevent_decrement_write_buckets_(bufev_p, res);
	}

	if (evbuffer_get_length(bufev->output) == 0) {
		event_del(&bufev->ev_write);
	}

	/*
	 * Invoke the user callback if our buffer is drained or below the
	 * low watermark.
	 */
	if ((res || !connected) &&
	    evbuffer_get_length(bufev->output) <= bufev->wm_write.low) {
		bufferevent_run_writecb_(bufev);
	}

	goto done;

 reschedule:
	if (evbuffer_get_length(bufev->output) == 0) {
		event_del(&bufev->ev_write);
	}
	goto done;

 error:
	bufferevent_disable(bufev, EV_WRITE);
	bufferevent_run_eventcb_(bufev, what);

 done:
	bufferevent_decref_and_unlock_(bufev);
}
コード例 #24
0
int
run_unmarshal(struct run *tmp,  struct evbuffer *evbuf)
{
  ev_uint32_t tag;
  while (evbuffer_get_length(evbuf) > 0) {
    if (evtag_peek(evbuf, &tag) == -1)
      return (-1);
    switch (tag) {

      case RUN_HOW:

        if (tmp->how_set)
          return (-1);
        if (evtag_unmarshal_string(evbuf, RUN_HOW, &tmp->how_data) == -1) {
          event_warnx("%s: failed to unmarshal how", __func__);
          return (-1);
        }
        tmp->how_set = 1;
        break;

      case RUN_SOME_BYTES:

        if (tmp->some_bytes_set)
          return (-1);
        if (evtag_payload_length(evbuf, &tmp->some_bytes_length) == -1)
          return (-1);
        if (tmp->some_bytes_length > evbuffer_get_length(evbuf))
          return (-1);
        if ((tmp->some_bytes_data = malloc(tmp->some_bytes_length)) == NULL)
          return (-1);
        if (evtag_unmarshal_fixed(evbuf, RUN_SOME_BYTES, tmp->some_bytes_data, tmp->some_bytes_length) == -1) {
          event_warnx("%s: failed to unmarshal some_bytes", __func__);
          return (-1);
        }
        tmp->some_bytes_set = 1;
        break;

      case RUN_FIXED_BYTES:

        if (tmp->fixed_bytes_set)
          return (-1);
        if (evtag_unmarshal_fixed(evbuf, RUN_FIXED_BYTES, tmp->fixed_bytes_data, (24)) == -1) {
          event_warnx("%s: failed to unmarshal fixed_bytes", __func__);
          return (-1);
        }
        tmp->fixed_bytes_set = 1;
        break;

      case RUN_NOTES:

        if (tmp->notes_length >= tmp->notes_num_allocated &&
            run_notes_expand_to_hold_more(tmp) < 0) {
          puts("HEY NOW");
          return (-1);
        }
        if (evtag_unmarshal_string(evbuf, RUN_NOTES, &tmp->notes_data[tmp->notes_length]) == -1) {
          event_warnx("%s: failed to unmarshal notes", __func__);
          return (-1);
        }
        ++tmp->notes_length;
        tmp->notes_set = 1;
        break;

      case RUN_LARGE_NUMBER:

        if (tmp->large_number_set)
          return (-1);
        if (evtag_unmarshal_int64(evbuf, RUN_LARGE_NUMBER, &tmp->large_number_data) == -1) {
          event_warnx("%s: failed to unmarshal large_number", __func__);
          return (-1);
        }
        tmp->large_number_set = 1;
        break;

      case RUN_OTHER_NUMBERS:

        if (tmp->other_numbers_length >= tmp->other_numbers_num_allocated &&
            run_other_numbers_expand_to_hold_more(tmp) < 0) {
          puts("HEY NOW");
          return (-1);
        }
        if (evtag_unmarshal_int(evbuf, RUN_OTHER_NUMBERS, &tmp->other_numbers_data[tmp->other_numbers_length]) == -1) {
          event_warnx("%s: failed to unmarshal other_numbers", __func__);
          return (-1);
        }
        ++tmp->other_numbers_length;
        tmp->other_numbers_set = 1;
        break;

      default:
        return -1;
    }
  }

  if (run_complete(tmp) == -1)
    return (-1);
  return (0);
}
コード例 #25
0
ファイル: tcp.c プロジェクト: atomic77/mosql-storage
static int bptree_message_incomplete(struct evbuffer *b) {
	// BTree messages also should contain a bpt_id
	int bsize = evbuffer_get_length(b);
	if (bsize < sizeof(uint16_t)) return 1;
	return 0;
}
コード例 #26
0
int
msg_unmarshal(struct msg *tmp,  struct evbuffer *evbuf)
{
  ev_uint32_t tag;
  while (evbuffer_get_length(evbuf) > 0) {
    if (evtag_peek(evbuf, &tag) == -1)
      return (-1);
    switch (tag) {

      case MSG_FROM_NAME:

        if (tmp->from_name_set)
          return (-1);
        if (evtag_unmarshal_string(evbuf, MSG_FROM_NAME, &tmp->from_name_data) == -1) {
          event_warnx("%s: failed to unmarshal from_name", __func__);
          return (-1);
        }
        tmp->from_name_set = 1;
        break;

      case MSG_TO_NAME:

        if (tmp->to_name_set)
          return (-1);
        if (evtag_unmarshal_string(evbuf, MSG_TO_NAME, &tmp->to_name_data) == -1) {
          event_warnx("%s: failed to unmarshal to_name", __func__);
          return (-1);
        }
        tmp->to_name_set = 1;
        break;

      case MSG_ATTACK:

        if (tmp->attack_set)
          return (-1);
        tmp->attack_data = kill_new();
        if (tmp->attack_data == NULL)
          return (-1);
        if (evtag_unmarshal_kill(evbuf, MSG_ATTACK, tmp->attack_data) == -1) {
          event_warnx("%s: failed to unmarshal attack", __func__);
          return (-1);
        }
        tmp->attack_set = 1;
        break;

      case MSG_RUN:

        if (tmp->run_length >= tmp->run_num_allocated &&
            msg_run_expand_to_hold_more(tmp) < 0) {
          puts("HEY NOW");
          return (-1);
        }
        tmp->run_data[tmp->run_length] = run_new();
        if (tmp->run_data[tmp->run_length] == NULL)
          return (-1);
        if (evtag_unmarshal_run(evbuf, MSG_RUN, tmp->run_data[tmp->run_length]) == -1) {
          event_warnx("%s: failed to unmarshal run", __func__);
          return (-1);
        }
        ++tmp->run_length;
        tmp->run_set = 1;
        break;

      default:
        return -1;
    }
  }

  if (msg_complete(tmp) == -1)
    return (-1);
  return (0);
}
コード例 #27
0
ファイル: httpd.c プロジェクト: topherx/forked-daapd
/* Thread: httpd */
void
httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf)
{
  unsigned char outbuf[128 * 1024];
  z_stream strm;
  struct evbuffer *gzbuf;
  struct evkeyvalq *headers;
  const char *param;
  int flush;
  int zret;
  int ret;

  if (!req)
    return;

  if (!evbuf || (evbuffer_get_length(evbuf) == 0))
    {
      DPRINTF(E_DBG, L_HTTPD, "Not gzipping body-less reply\n");

      goto no_gzip;
    }

  headers = evhttp_request_get_input_headers(req);

  param = evhttp_find_header(headers, "Accept-Encoding");
  if (!param)
    {
      DPRINTF(E_DBG, L_HTTPD, "Not gzipping; no Accept-Encoding header\n");

      goto no_gzip;
    }
  else if (!strstr(param, "gzip") && !strstr(param, "*"))
    {
      DPRINTF(E_DBG, L_HTTPD, "Not gzipping; gzip not in Accept-Encoding (%s)\n", param);

      goto no_gzip;
    }

  gzbuf = evbuffer_new();
  if (!gzbuf)
    {
      DPRINTF(E_LOG, L_HTTPD, "Could not allocate evbuffer for gzipped reply\n");

      goto no_gzip;
    }

  strm.zalloc = Z_NULL;
  strm.zfree = Z_NULL;
  strm.opaque = Z_NULL;

  /* Set up a gzip stream (the "+ 16" in 15 + 16), instead of a zlib stream (default) */
  zret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
  if (zret != Z_OK)
    {
      DPRINTF(E_DBG, L_HTTPD, "zlib setup failed: %s\n", zError(zret));

      goto out_fail_init;
    }

  strm.next_in = evbuffer_pullup(evbuf, -1);
  strm.avail_in = evbuffer_get_length(evbuf);

  flush = Z_NO_FLUSH;

  /* 2 iterations: Z_NO_FLUSH until input is consumed, then Z_FINISH */
  for (;;)
    {
      do
	{
	  strm.next_out = outbuf;
	  strm.avail_out = sizeof(outbuf);

	  zret = deflate(&strm, flush);
	  if (zret == Z_STREAM_ERROR)
	    {
	      DPRINTF(E_LOG, L_HTTPD, "Could not deflate data: %s\n", strm.msg);

	      goto out_fail_gz;
	    }

	  ret = evbuffer_add(gzbuf, outbuf, sizeof(outbuf) - strm.avail_out);
	  if (ret < 0)
	    {
	      DPRINTF(E_LOG, L_HTTPD, "Out of memory adding gzipped data to evbuffer\n");

	      goto out_fail_gz;
	    }
	}
      while (strm.avail_out == 0);

      if (flush == Z_FINISH)
	break;

      flush = Z_FINISH;
    }

  if (zret != Z_STREAM_END)
    {
      DPRINTF(E_LOG, L_HTTPD, "Compressed data not finalized!\n");

      goto out_fail_gz;
    }

  deflateEnd(&strm);

  headers = evhttp_request_get_output_headers(req);

  evhttp_add_header(headers, "Content-Encoding", "gzip");
  evhttp_send_reply(req, code, reason, gzbuf);

  evbuffer_free(gzbuf);

  /* Drain original buffer, as would be after evhttp_send_reply() */
  evbuffer_drain(evbuf, evbuffer_get_length(evbuf));

  return;

 out_fail_gz:
  deflateEnd(&strm);
 out_fail_init:
  evbuffer_free(gzbuf);
 no_gzip:
  evhttp_send_reply(req, code, reason, evbuf);
}
コード例 #28
0
ファイル: cache.c プロジェクト: JanX2/transmission
  if (cb == NULL)
    {
      cb = tr_new (struct cache_block, 1);
      cb->tor = torrent;
      cb->piece = piece;
      cb->offset = offset;
      cb->length = length;
      cb->block = _tr_block (torrent, piece, offset);
      cb->evbuf = evbuffer_new ();
      tr_ptrArrayInsertSorted (&cache->blocks, cb, cache_block_compare);
    }

  cb->time = tr_time ();

  assert (cb->length == length);
  evbuffer_drain (cb->evbuf, evbuffer_get_length (cb->evbuf));
  evbuffer_remove_buffer (writeme, cb->evbuf, cb->length);

  cache->cache_writes++;
  cache->cache_write_bytes += cb->length;

  return cacheTrim (cache);
}

int
tr_cacheReadBlock (tr_cache         * cache,
                   tr_torrent       * torrent,
                   tr_piece_index_t   piece,
                   uint32_t           offset,
                   uint32_t           len,
                   uint8_t          * setme)
コード例 #29
0
// Эта штука срабатывает, когда кто-то нам пишет
void connection::buff_on_read(struct bufferevent *bev, void *ctx) {
    connection* _this = static_cast<connection*>(ctx);

    log << "Sth read\n";

    // буфер с нашими данными
    evbuffer* input = bev->input;

    // копируем всё это дело в строку
    size_t len = evbuffer_get_length(bev->input);
    char* data = new char[len];
    if ((evbuffer_copyout(input, data, len)) < 0) {
        event_base_loopbreak(_this->evbase);
    } else {
        log << "Parsing...\n";
        // ПАРСИМ (TODO: здесь в оригинале должно быть всё красиво. Нужно смотреть тип запроса, обрабатывать все заголовки, вешать нормальные колбеки и много всего.), но сейчас нам важно поолучить только URL

        _this->parser.data = _this; // устанавливаем для парсера связь с внешним миром

        http_parser_settings settings;
        memset(&settings, 0, sizeof(settings));

        // устанавливаем обработчики
        settings.on_url = [](http_parser* p, const char* at, size_t len) -> int {
            // копируем URL
           // printf("Url: %.*s\n", (int)len, at);
            char* t = new char[len-1];
            memset(t, '\0', len*sizeof(char));
            strncpy(t, at+1, len-1); // len-1 т.к. там пробел
            // избавляемся от параметров
            for (char* i = t; *i; ++i) {
                if (*i == '?') { *i = '\0'; break; }
            }
            static_cast<connection*>(p->data)->client_request.uri = t;
            delete t;
            return 0;
        };

        settings.on_header_field = [](http_parser* p, const char* at, size_t len) -> int {return 0;};
        settings.on_header_value = [](http_parser* p, const char* at, size_t len) -> int {return 0;};
        settings.on_headers_complete = [](http_parser*) -> int {return 0;};

        size_t nparsed = http_parser_execute(&_this->parser, &settings, data, len);
        if (nparsed != len) {
            log << "Can't parse\n";
            event_base_loopbreak(_this->evbase);
        }

        // НА ЭТОМ ЭТАПЕ МЫ ВСЁ РАСПАРСИЛИ И ИМЕЕМ ЗАПОЛНЕННЫЙ РЕКВЕСТ (client_request)
//        _this->client_request.method = http_method_str(_this->parser.method);
        log << "URI=" << _this->client_request.uri << std::endl;

        // Пытаемся открыть требуемый файл и скрамливаем его клиенту

        int fd = open(_this->client_request.uri.c_str(), O_RDONLY);
        //вывод имени файла по байтам
//        for (auto& i: _this->client_request.uri) {
//            printf("%d ", i);
//        }
//        puts("");

        // Если не получилось - шлём ошибку
        if (fd < 0) {
            log << "No such file or directory\n";//perror("KEK");
            if ((send(_this->client_sock, response::not_found.c_str(), response::not_found.length(), MSG_NOSIGNAL)) < 0) {
                log << "cant't send!!!\n";
            }
        } else {
            // если всё окей
            if ((send(_this->client_sock, response::ok.c_str(), response::ok.length(), MSG_NOSIGNAL | MSG_MORE)) < 0) {
                log << "can't send\n";
            } else {
                struct stat stat_buf;
                fstat(fd, &stat_buf);

                // Посылаем файл
                ssize_t recv = sendfile( _this->client_sock, fd, nullptr, stat_buf.st_size);
                if (recv != stat_buf.st_size) {
                    log << "file not sent at all\n";
                }
            }

        }

        event_base_loopexit(_this->evbase, nullptr);
    }
}
コード例 #30
0
ファイル: read_cb.cpp プロジェクト: shanoasaber/server_src
void conn_read_cb(struct bufferevent *bev, void *arg)
{
    conn *c = (conn *)arg;
    user_callback *cb = (user_callback *)(c->data);

    struct evbuffer* input = bufferevent_get_input(bev);
    size_t total_len = evbuffer_get_length(input);

    while (1)
    {
        if (total_len < MSG_HEAD_SIZE) {
            goto conti;
        }
        else {
            unsigned char *buffer = evbuffer_pullup(input, MSG_HEAD_SIZE);
            if (NULL == buffer)
            {
                merror("evbuffer_pullup MSG_HEAD_SIZE failed!");
                goto err;
            }

            unsigned short *cur = (unsigned short *)buffer;
            unsigned int len = ntohs(*(unsigned int *)cur);
            cur += 2;

            if (MSG_MAX_SIZE < len)
            {
                merror("len:%d > MSG_MAX_SIZE!", len);
                goto err;
            }

            if (total_len < MSG_HEAD_SIZE + len)
                goto conti;

            size_t msg_len = MSG_HEAD_SIZE + len;
            buffer = evbuffer_pullup(input, msg_len);
            if (NULL == buffer)
            {
                merror("evbuffer_pullup msg_len failed!");
                goto err;
            }

            /* TODO frequency limit */

            /* callback */
            if (cb->rpc)
                (*(cb->rpc))(c, buffer, msg_len);

            if (evbuffer_drain(input, msg_len) < 0)
            {
                merror("evbuffer_drain failed!");
                goto err;
            }

            total_len -= msg_len;
        }
    }
    return;

err:
    mdebug("close sockect!");
    if (cb->disconnect) {
        (*(cb->disconnect))(c);
    }
    conn_decref(c);
    return;

conti:
    bufferevent_enable(bev, EV_READ);
    return;
}