Esempio n. 1
0
void AnnouncementApi::handleResponse(QNetworkReply *reply)
{
	try {
		if(reply->error() != QNetworkReply::NoError)
			throw ResponseError(reply->errorString());

		// TODO handle redirects

		const QString querytype = reply->property("QUERY_TYPE").toString();
		if(querytype == "announce")
			handleAnnounceResponse(reply);
		else if(querytype == "unlist")
			handleUnlistResponse(reply);
		else if(querytype == "refresh")
			handleRefreshResponse(reply);
		else if(querytype == "getlist")
			handleListingResponse(reply);
		else if(querytype == "getinfo")
			handleServerInfoResponse(reply);
		else // shouldn't happen
			qFatal("Unhandled Announcement API response query type");

	} catch(const ResponseError &e) {
		logger::error() << "Announce API error:" << e.error;
		emit error("Session announcement: " + e.error);
#ifndef NDEBUG
		logger::error() << "Announcement API error:" << QString::fromUtf8(reply->readAll());
#endif
	}

	reply->deleteLater();
}
static void
processDataFromClient(TConn *      const connectionP,
                      abyss_bool   const lastReqOnConn,
                      abyss_bool * const keepAliveP) {

    TSession session;

    RequestInit(&session, connectionP);

    session.serverDeniesKeepalive = lastReqOnConn;
        
    RequestRead(&session);
    if (session.status == 0) {
        if (session.version.major >= 2)
            ResponseStatus(&session, 505);
        else if (!RequestValidURI(&session))
            ResponseStatus(&session, 400);
        else
            runUserHandler(&session, connectionP->server->srvP);
    }
    assert(session.status != 0);
    
    if (session.responseStarted)
        HTTPWriteEndChunk(&session);
    else
        ResponseError(&session);

    *keepAliveP = HTTPKeepalive(&session);
    
    SessionLog(&session);

    RequestFree(&session);
}
Esempio n. 3
0
static void
sendError(TSession *   const abyssSessionP,
          unsigned int const status) {
/*----------------------------------------------------------------------------
  Send an error response back to the client.

-----------------------------------------------------------------------------*/
    ResponseStatus(abyssSessionP, (uint16_t) status);
    ResponseError(abyssSessionP);
}
Esempio n. 4
0
void AnnouncementApi::handleServerInfoResponse(QNetworkReply *reply)
{
	QJsonParseError error;
	QByteArray body = reply->readAll();
	QJsonDocument doc = QJsonDocument::fromJson(body, &error);
	if(error.error != QJsonParseError::NoError)
		throw ResponseError(QStringLiteral("Error parsing API response: %1").arg(error.errorString()));

	if(!doc.isObject())
		throw ResponseError(QStringLiteral("Expected object!"));

	QJsonObject obj = doc.object();

	QString apiname = obj.value("api_name").toString();
	if(apiname != "drawpile-session-list")
		throw ResponseError(QStringLiteral("This is not a Drawpile listing server!"));

	ListServerInfo info {
		obj.value("version").toString(),
		obj.value("name").toString().trimmed(),
		obj.value("description").toString().trimmed(),
		obj.value("favicon").toString()
	};

	if(info.version.isEmpty())
		throw ResponseError(QStringLiteral("API version not specified!"));

	if(!info.version.startsWith("1."))
		throw ResponseError(QStringLiteral("Unsupported API version!"));

	if(info.name.isEmpty())
		throw ResponseError(QStringLiteral("Server name missing!"));

	emit serverInfo(info);
}
Esempio n. 5
0
void AnnouncementApi::handleListingResponse(QNetworkReply *reply)
{
	QJsonParseError error;
	QByteArray body = reply->readAll();
	QJsonDocument doc = QJsonDocument::fromJson(body, &error);
	if(error.error != QJsonParseError::NoError)
		throw ResponseError(QStringLiteral("Error parsing announcement response: %1").arg(error.errorString()));

	QList<Session> sessions;

	if(!doc.isArray())
		throw ResponseError(QStringLiteral("Expected array of session descriptions!"));

	for(const QJsonValue &jsv : doc.array()) {
		if(!jsv.isObject())
			throw ResponseError(QStringLiteral("Expected session description!"));
		const QJsonObject obj = jsv.toObject();

		QDateTime started = QDateTime::fromString(obj["started"].toString(), Qt::ISODate);
		started.setTimeSpec(Qt::UTC);

		sessions << Session {
			obj["host"].toString(),
			obj["port"].toInt(),
			obj["id"].toString(),
			protocol::ProtocolVersion::fromString(obj["protocol"].toString()),
			obj["title"].toString(),
			obj["users"].toInt(),
			obj["usernames"].toVariant().toStringList(),
			obj["password"].toBool(),
			obj["nsfm"].toBool(),
			obj["owner"].toString(),
			started
		};
	}

	emit sessionListReceived(sessions);
}
Esempio n. 6
0
void AnnouncementApi::handleAnnounceResponse(QNetworkReply *reply)
{
	QJsonParseError error;
	QByteArray body = reply->readAll();
	QJsonDocument doc = QJsonDocument::fromJson(body, &error);
	if(error.error != QJsonParseError::NoError)
		throw ResponseError(QStringLiteral("Error parsing announcement response: %1").arg(error.errorString()));

	Announcement a;
	a.apiUrl = reply->property("API_URL").toUrl();
	a.id = reply->property("SESSION_ID").toString();
	a.updateKey = doc.object()["key"].toString();
	a.listingId = doc.object()["id"].toInt();

	logger::debug() << "Announced session. Got listing ID" << a.listingId;

	emit sessionAnnounced(a);

	QString welcome = doc.object()["message"].toString();
	if(!welcome.isEmpty())
		emit messageReceived(doc.object()["message"].toString());
}
Esempio n. 7
0
static void
processRequestFromClient(TConn *  const connectionP,
                         bool     const lastReqOnConn,
                         uint32_t const timeout,
                         bool *   const keepAliveP) {
/*----------------------------------------------------------------------------
   Get and execute one HTTP request from client connection *connectionP,
   through the connection buffer.  I.e. Some of the request may already be in
   the connection buffer, and we may leave some of later requests in the
   connection buffer.

   In fact, due to timing considerations, we assume the client has begun
   sending the request, which as a practical matter means Caller has already
   deposited some of it in the connection buffer.

   If there isn't one full request in the buffer now, we wait for one full
   request to come through the buffer, up to 'timeout'.

   We return as *keepAliveP whether Caller should keep the connection
   alive for a while for possible future requests from the client, based
   on 'lastReqOnConn' and the content of the HTTP request.

   Executing the request consists primarily of calling the URI handlers that
   are associated with the connection (*connectionP), passing each the request
   information we read.  Each handler can respond according to the HTTP method
   (GET, POST, etc) and URL etc, and that response may be either to
   execute the request and send the response or refuse the request and let
   us call the next one in the list.
-----------------------------------------------------------------------------*/
    TSession session;
    const char * error;
    uint16_t httpErrorCode;

    RequestInit(&session, connectionP);

    session.serverDeniesKeepalive = lastReqOnConn;
        
    RequestRead(&session, timeout, &error, &httpErrorCode);

    if (error) {
        ResponseStatus(&session, httpErrorCode);
        ResponseError2(&session, error);
        xmlrpc_strfree(error);
    } else {
        if (session.version.major >= 2)
            handleReqTooNewHttpVersion(&session);
        else if (!RequestValidURI(&session))
            handleReqInvalidURI(&session);
        else
            runUserHandler(&session, connectionP->server->srvP);
    }

    assert(session.status != 0);

    if (session.responseStarted)
        HTTPWriteEndChunk(&session);
    else
        ResponseError(&session);

    *keepAliveP = HTTPKeepalive(&session);

    SessionLog(&session);

    RequestFree(&session);
}
Esempio n. 8
0
DWORD yathCSessionThread::Execute()
{
	if (m_Connection == NULL) return -1;

#ifdef _DEBUG
	::Beep( 2000, 200);
#endif

	{
		int ReceivedDataSize;

		//while ( !m_Connection->ReadData( m_Buffer, sizeof( m_Buffer), ReceivedDataSize, FALSE)){
		while ( !m_Connection->ReadDataBlock( m_Buffer, sizeof( m_Buffer), ReceivedDataSize)){
			if ( ReceivedDataSize > 0){
				int Command;
				if ( ::yathRetriveChunkStamp( m_Buffer, ReceivedDataSize, Command)){
					BOOL ResponseResult = FALSE;
					switch ( Command) {
					case yathcmdLISTFILES:
						ResponseResult = ResponseListFiles();
						break;
					case yathcmdCHANGEDIR:
						ResponseResult = ResponseChangeDir();
						break;
					case yathcmdGETCURRENTRIR:
						ResponseResult = ResponseError();
						break;
					case yathcmdMAKEDIR:
						ResponseResult = ResponseCreateDir();
						break;
					case yathcmdREMOVEFILE:
						ResponseResult = ResponseRemoveFile();
						break;
					case yathcmdREMOVEDIR:
						ResponseResult = ResponseRemoveDir();
						break;
					case yathcmdGETFILE:
						ResponseResult = ResponseGetFile();
						break;
					case yathcmdPUTFILE:
						ResponseResult = ResponsePutFile();
						break;
					case yathcmdMOVE:
						ResponseResult = ResponseMove();
						break;
					default:;
						ResponseResult = ResponseError();
					}

					if ( !ResponseResult) goto StopSession;
				}
			} else goto StopSession;
		}
	}
	
StopSession:	
	m_Connection->Done();

#ifdef _DEBUG	
	::Beep( 1000, 200);
#endif

	return 0;
}
Esempio n. 9
0
void ServerFunc(TConn *c)
{
	TRequest r;
	uint32 ka = 0;

	/* sanity */
	if (!c) {
		return;
	}

	ka=c->server->keepalivemaxconn;
	c->pool = ap_make_sub_pool( c->server->pool );
	c->server->stat_conns++;

	RequestInit(&r,c);

	/* tell connection handlers - new connection */
	ap_conn_init_modules( c );

	while (ka--)
	{
		c->start_time = ap_time();

		/* Wait to read until timeout */
		if (!ConnRead(c,c->server->keepalivetimeout)) {
			break;
		}

/* CODE_PROBE_1("Server - Req Read Start (%x)",c); */
		if (RequestRead(&r))
		{
			/* Check if it is the last keepalive */
			if (ka==1) {
				r.keepalive=FALSE;
			}	

			r.cankeepalive=r.keepalive;

			if (r.status==0) {
				if (r.versionmajor>=2) {
					ResponseStatus(&r,505);
				} else if (!RequestValidURI(&r)) {
					ResponseStatus(&r,400);
				} else {
					if( ap_invoke_handler( &r ) == DECLINED ) {
						((HANDLER)(c->server->defaulthandler))(&r);
					}
				}
			}
		}
/* CODE_PROBE_1("Server - Req Read End (%x)",c); */
       		
		HTTPWriteEnd(&r);
		ConnWriteFlush( c );

		if (!r.done)
			ResponseError(&r);

		RequestLog(&r);

		/* do flow stat update */
		c->server->stat_inbytes += c->inbytes;
		c->server->stat_outbytes += c->outbytes;
		c->server->stat_data_time += ap_time() - c->start_time;

                if( c->server->stopped ) {
                        break;
		}
		if (!(r.keepalive && r.cankeepalive)) {
			break;
		}

		RequestReset(&r,c);
		ConnReadInit(c);		
/* CODE_PROBE_1("Server - ConnReadInit - Bottom (%x)",c); */
	}

	/* tell connection handlers session complete */
	ap_conn_exit_modules( c );
	ap_destroy_pool( c->pool );
	RequestFree(&r);

	SocketClose(&(c->socket));
}
Esempio n. 10
0
abyss_bool handler_hook(TSession * r)
{
	//char *mime = "text/html";
	char buf[80] = "HTTP/1.1 200 OK\n";
	switch_stream_handle_t stream = { 0 };
	char *command;
	int i;
	TTableItem *ti;
	char *fs_user = NULL, *fs_domain = NULL;
	char *path_info = NULL;
	abyss_bool ret = TRUE;
	int html = 0, text = 0, xml = 0;
	const char *api_str;

	stream.data = r;
	stream.write_function = http_stream_write;
	stream.raw_write_function = http_stream_raw_write;

	if (!r || !r->requestInfo.uri) {
		return FALSE;
	}
	
	if ((command = strstr(r->requestInfo.uri, "/api/"))) {
		command += 5;
	} else if ((command = strstr(r->requestInfo.uri, "/webapi/"))) {
		command += 8;
		html++;
	} else if ((command = strstr(r->requestInfo.uri, "/txtapi/"))) {
		command += 8;
		text++;
	} else if ((command = strstr(r->requestInfo.uri, "/xmlapi/"))) {
		command += 8;
		xml++;
	} else {
		return FALSE;
	}

	if ((path_info = strchr(command, '/'))) {
		*path_info++ = '\0';
	}

	for (i = 0; i < r->response_headers.size; i++) {
		ti = &r->response_headers.item[i];
		if (!strcasecmp(ti->name, "freeswitch-user")) {
			fs_user = ti->value;
		} else if (!strcasecmp(ti->name, "freeswitch-domain")) {
			fs_domain = ti->value;
		}
	}

	if (is_authorized(r, command)) {
		goto auth;
	}

	ret = TRUE;
	goto end;

  auth:

	if (switch_event_create(&stream.param_event, SWITCH_EVENT_API) == SWITCH_STATUS_SUCCESS) {
		const char *const content_length = RequestHeaderValue(r, "content-length");

		if (html)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "Content-type", "text/html");
		else if (text)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "Content-type", "text/plain");
		else if (xml)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "Content-type", "text/xml");
		if (fs_user)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "FreeSWITCH-User", fs_user);
		if (fs_domain)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "FreeSWITCH-Domain", fs_domain);
		if (path_info)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-Path-Info", path_info);
		switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-URI", r->requestInfo.uri);
		if (r->requestInfo.query)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-QUERY", r->requestInfo.query);
		if (r->requestInfo.host)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-HOST", r->requestInfo.host);
		if (r->requestInfo.from)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-FROM", r->requestInfo.from);
		if (r->requestInfo.useragent)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-USER-AGENT", r->requestInfo.useragent);
		if (r->requestInfo.referer)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-REFERER", r->requestInfo.referer);
		if (r->requestInfo.requestline)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-REQUESTLINE", r->requestInfo.requestline);
		if (r->requestInfo.user)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-USER", r->requestInfo.user);
		if (r->requestInfo.port)
			switch_event_add_header(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-PORT", "%u", r->requestInfo.port);
		if (r->requestInfo.query || content_length) {
			char *q, *qd;
			char *next;
			char *query = (char *) r->requestInfo.query;
			char *name, *val;
			char qbuf[8192] = "";

			if (r->requestInfo.method == m_post && content_length) {
				int len = atoi(content_length);
				int qlen = 0;

				if (len > 0) {
					int succeeded;
					char *qp = qbuf;
					do {
						int blen = r->conn->buffersize - r->conn->bufferpos;

						if ((qlen + blen) > len) {
							blen = len - qlen;
						}

						qlen += blen;

						if (qlen > sizeof(qbuf)) {
							break;
						}

						memcpy(qp, r->conn->buffer + r->conn->bufferpos, blen);
						qp += blen;

						if (qlen >= len) {
							break;
						}
					} while ((succeeded = ConnRead(r->conn, 2000)));

					query = qbuf;
				}
			}
			if (query) {
				switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-QUERY", query);

				qd = strdup(query);
				switch_assert(qd != NULL);

				q = qd;
				next = q;

				do {
					char *p;

					if ((next = strchr(next, '&'))) {
						*next++ = '\0';
					}

					for (p = q; p && *p; p++) {
						if (*p == '+') {
							*p = ' ';
						}
					}

					switch_url_decode(q);

					name = q;
					if ((val = strchr(name, '='))) {
						*val++ = '\0';
						switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, name, val);
					}
					q = next;
				} while (q != NULL);

				free(qd);
			}
		}
	}
	//ResponseChunked(r);

	//ResponseContentType(r, mime);
	//ResponseWrite(r);

	HTTPWrite(r, buf, (uint32_t) strlen(buf));

	//HTTPWrite(r, "<pre>\n\n", 7);

	/* generation of the date field */
	{
		const char *dateValue;

		DateToString(r->date, &dateValue);

		if (dateValue) {
			ResponseAddField(r, "Date", dateValue);
		}
	}


	/* Generation of the server field */
	ResponseAddField(r, "Server", "FreeSWITCH-" SWITCH_VERSION_FULL "-mod_xml_rpc");

	if (html) {
		ResponseAddField(r, "Content-Type", "text/html");
	} else if (text) {
		ResponseAddField(r, "Content-Type", "text/plain");
	} else if (xml) {
		ResponseAddField(r, "Content-Type", "text/xml");
	}

	for (i = 0; i < r->response_headers.size; i++) {
		ti = &r->response_headers.item[i];
		ConnWrite(r->conn, ti->name, (uint32_t) strlen(ti->name));
		ConnWrite(r->conn, ": ", 2);
		ConnWrite(r->conn, ti->value, (uint32_t) strlen(ti->value));
		ConnWrite(r->conn, CRLF, 2);
	}

	switch_snprintf(buf, sizeof(buf), "Connection: close\r\n");
	ConnWrite(r->conn, buf, (uint32_t) strlen(buf));

	if (html || text || xml) {
		ConnWrite(r->conn, "\r\n", 2);
	}

	if (switch_stristr("unload", command) && switch_stristr("mod_xml_rpc", r->requestInfo.query)) {
		command = "bgapi";
		api_str = "unload mod_xml_rpc";
	} else if (switch_stristr("reload", command) && switch_stristr("mod_xml_rpc", r->requestInfo.query)) {
		command = "bgapi";
		api_str = "reload mod_xml_rpc";
	} else {
		api_str = r->requestInfo.query;
	}

	if (switch_api_execute(command, api_str, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
		ResponseStatus(r, 200);
		r->responseStarted = TRUE;
		//r->done = TRUE;
	} else {
		ResponseStatus(r, 404);
		ResponseError(r);
	}

	//SocketClose(&(r->conn->socket));

	HTTPWriteEnd(r);
	//if (r->conn->channelP)
	//ConnKill(r->conn);
	//ChannelInterrupt(r->conn->channelP);
	//ConnClose(r->conn);
	//ChannelDestroy(r->conn->channelP);
	r->requestInfo.keepalive = 0;

  end:

	return ret;
}